/**
 @file sys_tmm_flexe.c

 @author  Copyright (C) 2019 Centec Networks Inc.  All rights reserved.

 @date 2019-10-22

 @version v0.1

*/

/****************************************************************************
 *
* Header Files
*
****************************************************************************/
#include "sal.h"
#include "ctc_error.h"
#include "ctc_debug.h"
#include "ctc_interrupt.h"
#include "ctc_warmboot.h"
#include "drv_api.h"
#include "usw/include/drv_common.h"

#include "sys_usw_common.h"
#include "sys_usw_interrupt.h"
#include "sys_usw_register.h"
#include "sys_usw_datapath.h"
#include "sys_tmm_datapath.h"
#include "sys_usw_flexe.h"
#include "sys_tmm_flexe.h"
#include "sys_usw_l2_fdb.h"
#include "sys_usw_port.h"
#include "sys_tmm_serdes.h"
#include "sys_tmm_mcu.h"

/****************************************************************************
 *
* Defines and Macros
*
*****************************************************************************/

#define DRV_IOW_FIELD_NZ(lchip, memid, fieldid, value, ptr, inst, index) \
        DRV_IOW_FIELD(lchip, memid, fieldid, value, ptr) 

#define TSINGMA_DUMP_PRINT  if(g_dmps_dbg_sw && g_tm_dump_fp) sal_fprintf

#if defined(_SAL_LINUX_KM)
#define FLEXE_DUMP(FMT, ...)
#else
#define FLEXE_DUMP(FMT, ...)
#endif

#ifdef NOT_USED
#define FLEXE_DBG_PRINTF(FMT, ...)   ctc_sal_print_func(FMT, ##__VA_ARGS__)
#else
#define FLEXE_DBG_PRINTF(FMT, ...)
#endif

/****************************************************************************
 *
* Global and Declaration
*
*****************************************************************************/
const uint32 g_flexe_oh_field_info[FLEXE_OH_FIELD_MAX][FLEXE_OH_INFO_ALL] = 
{   /*OH field name              valid flag  block 0~15  start bit  mask*/
    /*FLEXE_OH_FIELD_C_0     */ {TRUE,       0,          8,         0xfffffeff},
    /*FLEXE_OH_FIELD_C_1     */ {TRUE,       2,          0,         0xfffffffe},
    /*FLEXE_OH_FIELD_C_2     */ {TRUE,       4,          0,         0xfffffffe},
    /*FLEXE_OH_FIELD_OMF     */ {FALSE,      0,          9,         0xfffffdff},
    /*FLEXE_OH_FIELD_RPF     */ {FALSE,      0,          10,        0xfffffbff},
    /*FLEXE_OH_FIELD_SC      */ {TRUE,       0,          11,        0xfffff7ff},
    /*FLEXE_OH_FIELD_GRP_NUM */ {TRUE,       0,          12,        0x00000fff},
    /*FLEXE_OH_FIELD_MAP     */ {TRUE,       2,          1,         0xfffffe01},
    /*FLEXE_OH_FIELD_INST_NUM*/ {TRUE,       2,          9,         0xfffe01ff},
    /*FLEXE_OH_FIELD_CAL_A   */ {TRUE,       4,          1,         0xfffe0001},
    /*FLEXE_OH_FIELD_CAL_B   */ {TRUE,       4,          17,        0x0001ffff},
    /*FLEXE_OH_FIELD_CAL_B_15*/ {TRUE,       5,          0,         0xfffffffe},
    /*FLEXE_OH_FIELD_CR      */ {TRUE,       5,          1,         0xfffffffd},
    /*FLEXE_OH_FIELD_CA      */ {TRUE,       5,          2,         0xfffffffb},
};

const sys_flexe_oh_halfblk_fld_t g_halfblk_fld[5] = 
{
   /*halfblk id  field number  field*/
/* blk_idx 0 */ {0,          2,            {FLEXE_OH_FIELD_C_0,      FLEXE_OH_FIELD_GRP_NUM,                         }},
/* blk_idx 1 */ {2,          3,            {FLEXE_OH_FIELD_C_1,      FLEXE_OH_FIELD_MAP,     FLEXE_OH_FIELD_INST_NUM,}},
/* blk_idx 2 */ {4,          3,            {FLEXE_OH_FIELD_C_2,      FLEXE_OH_FIELD_CAL_A,   FLEXE_OH_FIELD_CAL_B,   }},
/* blk_idx 3 */ {5,          3,            {FLEXE_OH_FIELD_CAL_B_15, FLEXE_OH_FIELD_CR,      FLEXE_OH_FIELD_CA,      }},
/* blk_idx 4 */ {0,          1,            {FLEXE_OH_FIELD_SC                                                        }},
};

/* inst_num * 2, indicate one is for fall, the other is for rise */
const uint32 g_cr_intr_list[SYS_FLEXE_MAX_INST_CNT*2][SYS_FLEXE_INTR_BIT_BUTT] = {
   /*bmp idx  inst  CR  CR mask*/
    {1,       0,    0,  0x00000040}, /*Inst 0 CR fall*/
    {1,       0,    1,  0x00000080}, /*Inst 0 CR rise*/
    {1,       1,    0,  0x00080000}, /*Inst 1 CR fall*/
    {1,       1,    1,  0x00100000}, /*Inst 1 CR rise*/
    {2,       2,    0,  0x00000001}, /*Inst 2 CR fall*/
    {2,       2,    1,  0x00000002}, /*Inst 2 CR rise*/
    {2,       3,    0,  0x00002000}, /*Inst 3 CR fall*/
    {2,       3,    1,  0x00004000}, /*Inst 3 CR rise*/
    {2,       4,    0,  0x04000000}, /*Inst 4 CR fall*/
    {2,       4,    1,  0x08000000}, /*Inst 4 CR rise*/
    {3,       5,    0,  0x00000080}, /*Inst 5 CR fall*/
    {3,       5,    1,  0x00000100}, /*Inst 5 CR rise*/
    {3,       6,    0,  0x00100000}, /*Inst 6 CR fall*/
    {3,       6,    1,  0x00200000}, /*Inst 6 CR rise*/
    {4,       7,    0,  0x00000002}, /*Inst 7 CR fall*/
    {4,       7,    1,  0x00000004}, /*Inst 7 CR rise*/
};

const uint32 g_ca_intr_list[SYS_FLEXE_MAX_INST_CNT*2][SYS_FLEXE_INTR_BIT_BUTT] = {
  /*bmp idx  inst  CA  CA mask*/
   {1,       0,    0,  0x00000010}, /*Inst 0 CA fall*/
   {1,       0,    1,  0x00000020}, /*Inst 0 CA rise*/
   {1,       1,    0,  0x00020000}, /*Inst 1 CA fall*/
   {1,       1,    1,  0x00040000}, /*Inst 1 CA rise*/
   {1,       2,    0,  0x40000000}, /*Inst 2 CA fall*/
   {1,       2,    1,  0x80000000}, /*Inst 2 CA rise*/
   {2,       3,    0,  0x00000800}, /*Inst 3 CA fall*/
   {2,       3,    1,  0x00001000}, /*Inst 3 CA rise*/
   {2,       4,    0,  0x01000000}, /*Inst 4 CA fall*/
   {2,       4,    1,  0x02000000}, /*Inst 4 CA rise*/
   {3,       5,    0,  0x00000020}, /*Inst 5 CA fall*/
   {3,       5,    1,  0x00000040}, /*Inst 5 CA rise*/
   {3,       6,    0,  0x00040000}, /*Inst 6 CA fall*/
   {3,       6,    1,  0x00080000}, /*Inst 6 CA rise*/
   {3,       7,    0,  0x80000000}, /*Inst 7 CA fall*/
   {4,       7,    1,  0x00000001}, /*Inst 7 CA rise*/
};

const uint32 g_ohlock_intr_list[SYS_FLEXE_MAX_INST_CNT*2][SYS_FLEXE_INTR_BIT_BUTT] = {
  /*bmp idx  inst  OHL OHL mask*/
   {0,       0,    1,  0x80000000}, /*Inst 0 OH Lock*/
   {0,       1,    1,  0x40000000}, /*Inst 1 OH Lock*/
   {0,       2,    1,  0x20000000}, /*Inst 2 OH Lock*/
   {0,       3,    1,  0x10000000}, /*Inst 3 OH Lock*/
   {0,       4,    1,  0x08000000}, /*Inst 4 OH Lock*/
   {0,       5,    1,  0x04000000}, /*Inst 5 OH Lock*/
   {0,       6,    1,  0x02000000}, /*Inst 6 OH Lock*/
   {0,       7,    1,  0x01000000}, /*Inst 7 OH Lock*/
   {0,       0,    0,  0x00800000}, /*Inst 0 OH LockLos*/
   {0,       1,    0,  0x00400000}, /*Inst 1 OH LockLos*/
   {0,       2,    0,  0x00200000}, /*Inst 2 OH LockLos*/
   {0,       3,    0,  0x00100000}, /*Inst 3 OH LockLos*/
   {0,       4,    0,  0x00080000}, /*Inst 4 OH LockLos*/
   {0,       5,    0,  0x00040000}, /*Inst 5 OH LockLos*/
   {0,       6,    0,  0x00020000}, /*Inst 6 OH LockLos*/
   {0,       7,    0,  0x00010000}, /*Inst 7 OH LockLos*/
};

const uint32 g_ohmflock_intr_list[SYS_FLEXE_MAX_INST_CNT*2][SYS_FLEXE_INTR_BIT_BUTT] = {
  /*bmp idx  inst  OHML OHML mask*/
   {0,       0,    1,  0x00000100}, /*Inst 0 OHMF Lock*/
   {0,       1,    1,  0x00008000}, /*Inst 1 OHMF Lock*/
   {0,       2,    1,  0x00004000}, /*Inst 2 OHMF Lock*/
   {0,       3,    1,  0x00002000}, /*Inst 3 OHMF Lock*/
   {0,       4,    1,  0x00001000}, /*Inst 4 OHMF Lock*/
   {0,       5,    1,  0x00000800}, /*Inst 5 OHMF Lock*/
   {0,       6,    1,  0x00000400}, /*Inst 6 OHMF Lock*/
   {0,       7,    1,  0x00000200}, /*Inst 7 OHMF Lock*/
   {0,       0,    0,  0x00000080}, /*Inst 0 OHMF LockLos*/
   {0,       1,    0,  0x00000040}, /*Inst 1 OHMF LockLos*/
   {0,       2,    0,  0x00000020}, /*Inst 2 OHMF LockLos*/
   {0,       3,    0,  0x00000010}, /*Inst 3 OHMF LockLos*/
   {0,       4,    0,  0x00000008}, /*Inst 4 OHMF LockLos*/
   {0,       5,    0,  0x00000004}, /*Inst 5 OHMF LockLos*/
   {0,       6,    0,  0x00000002}, /*Inst 6 OHMF LockLos*/
   {0,       7,    0,  0x00000001}, /*Inst 7 OHMF LockLos*/
};

const uint32 g_rpf_intr_list[SYS_FLEXE_MAX_INST_CNT*2][SYS_FLEXE_INTR_BIT_BUTT] = {
  /*bmp idx  inst  RPF RPF mask*/
   {1,       0,    0,  0x00000008}, /*Inst 0 RPF fall*/
   {1,       0,    1,  0x00000004}, /*Inst 0 RPF rise*/
   {1,       1,    0,  0x00010000}, /*Inst 1 RPF fall*/
   {1,       1,    1,  0x00008000}, /*Inst 1 RPF rise*/
   {1,       2,    0,  0x20000000}, /*Inst 2 RPF fall*/
   {1,       2,    1,  0x10000000}, /*Inst 2 RPF rise*/
   {2,       3,    0,  0x00000400}, /*Inst 3 RPF fall*/
   {2,       3,    1,  0x00000200}, /*Inst 3 RPF rise*/
   {2,       4,    0,  0x00800000}, /*Inst 4 RPF fall*/
   {2,       4,    1,  0x00400000}, /*Inst 4 RPF rise*/
   {3,       5,    0,  0x00000010}, /*Inst 5 RPF fall*/
   {3,       5,    1,  0x00000008}, /*Inst 5 RPF rise*/
   {3,       6,    0,  0x00020000}, /*Inst 6 RPF fall*/
   {3,       6,    1,  0x00010000}, /*Inst 6 RPF rise*/
   {3,       7,    0,  0x40000000}, /*Inst 7 RPF fall*/
   {3,       7,    1,  0x20000000}, /*Inst 7 RPF rise*/
};

/*
  TblID Address    Number EntrySZ Fields   Type            Slice     SDB  TblName
  ---------------------------------------------------------------------------------------
  3006  0x61050080 8      20      138      NORMAL           -         N   FlexeMgrInterruptFunc
  =======================================================================================
  FldID    Word     Bit      SegLen   TotalLen Name
  ---------------------------------------------------------------------------------------
  0        0        31       1        1        funcIntrFlexeOhLock0
  8        0        23       1        1        funcIntrFlexeOhLockLos0
  16       0        8        1        1        funcIntrFlexeOhMfLock0
  24       0        7        1        1        funcIntrFlexeOhMfLockLos0
  38       1        4        1        1        funcIntrFlexeOhRxChange_0_rx2RxCaFalling
  39       1        5        1        1        funcIntrFlexeOhRxChange_0_rx2RxCaRising
  40       1        6        1        1        funcIntrFlexeOhRxChange_0_rx2RxCrFalling
  41       1        7        1        1        funcIntrFlexeOhRxChange_0_rx2RxCrRising
  43       1        3        1        1        funcIntrFlexeOhRxChange_0_rx2RxRpfFalling
  44       1        2        1        1        funcIntrFlexeOhRxChange_0_rx2RxRpfRising

  1        0        30       1        1        funcIntrFlexeOhLock1
  9        0        22       1        1        funcIntrFlexeOhLockLos1
  17       0        15       1        1        funcIntrFlexeOhMfLock1
  25       0        6        1        1        funcIntrFlexeOhMfLockLos1
  51       1        17       1        1        funcIntrFlexeOhRxChange_1_rx2RxCaFalling
  52       1        18       1        1        funcIntrFlexeOhRxChange_1_rx2RxCaRising
  53       1        19       1        1        funcIntrFlexeOhRxChange_1_rx2RxCrFalling
  54       1        20       1        1        funcIntrFlexeOhRxChange_1_rx2RxCrRising
  56       1        16       1        1        funcIntrFlexeOhRxChange_1_rx2RxRpfFalling
  57       1        15       1        1        funcIntrFlexeOhRxChange_1_rx2RxRpfRising

  2        0        29       1        1        funcIntrFlexeOhLock2
  10       0        21       1        1        funcIntrFlexeOhLockLos2
  18       0        14       1        1        funcIntrFlexeOhMfLock2
  26       0        5        1        1        funcIntrFlexeOhMfLockLos2
  64       1        30       1        1        funcIntrFlexeOhRxChange_2_rx2RxCaFalling
  65       1        31       1        1        funcIntrFlexeOhRxChange_2_rx2RxCaRising
  66       2        0        1        1        funcIntrFlexeOhRxChange_2_rx2RxCrFalling
  67       2        1        1        1        funcIntrFlexeOhRxChange_2_rx2RxCrRising
  69       1        29       1        1        funcIntrFlexeOhRxChange_2_rx2RxRpfFalling
  70       1        28       1        1        funcIntrFlexeOhRxChange_2_rx2RxRpfRising

  3        0        28       1        1        funcIntrFlexeOhLock3
  11       0        20       1        1        funcIntrFlexeOhLockLos3
  19       0        13       1        1        funcIntrFlexeOhMfLock3
  27       0        4        1        1        funcIntrFlexeOhMfLockLos3
  77       2        11       1        1        funcIntrFlexeOhRxChange_3_rx2RxCaFalling
  78       2        12       1        1        funcIntrFlexeOhRxChange_3_rx2RxCaRising
  79       2        13       1        1        funcIntrFlexeOhRxChange_3_rx2RxCrFalling
  80       2        14       1        1        funcIntrFlexeOhRxChange_3_rx2RxCrRising
  82       2        10       1        1        funcIntrFlexeOhRxChange_3_rx2RxRpfFalling
  83       2        9        1        1        funcIntrFlexeOhRxChange_3_rx2RxRpfRising

  4        0        27       1        1        funcIntrFlexeOhLock4
  12       0        19       1        1        funcIntrFlexeOhLockLos4
  20       0        12       1        1        funcIntrFlexeOhMfLock4
  28       0        3        1        1        funcIntrFlexeOhMfLockLos4
  90       2        24       1        1        funcIntrFlexeOhRxChange_4_rx2RxCaFalling
  91       2        25       1        1        funcIntrFlexeOhRxChange_4_rx2RxCaRising
  92       2        26       1        1        funcIntrFlexeOhRxChange_4_rx2RxCrFalling
  93       2        27       1        1        funcIntrFlexeOhRxChange_4_rx2RxCrRising
  95       2        23       1        1        funcIntrFlexeOhRxChange_4_rx2RxRpfFalling
  96       2        22       1        1        funcIntrFlexeOhRxChange_4_rx2RxRpfRising

  5        0        26       1        1        funcIntrFlexeOhLock5
  13       0        18       1        1        funcIntrFlexeOhLockLos5
  21       0        11       1        1        funcIntrFlexeOhMfLock5
  29       0        2        1        1        funcIntrFlexeOhMfLockLos5
  103      3        5        1        1        funcIntrFlexeOhRxChange_5_rx2RxCaFalling
  104      3        6        1        1        funcIntrFlexeOhRxChange_5_rx2RxCaRising
  105      3        7        1        1        funcIntrFlexeOhRxChange_5_rx2RxCrFalling
  106      3        8        1        1        funcIntrFlexeOhRxChange_5_rx2RxCrRising
  108      3        4        1        1        funcIntrFlexeOhRxChange_5_rx2RxRpfFalling
  109      3        3        1        1        funcIntrFlexeOhRxChange_5_rx2RxRpfRising

  6        0        25       1        1        funcIntrFlexeOhLock6
  14       0        17       1        1        funcIntrFlexeOhLockLos6
  22       0        10       1        1        funcIntrFlexeOhMfLock6
  30       0        1        1        1        funcIntrFlexeOhMfLockLos6
  116      3        18       1        1        funcIntrFlexeOhRxChange_6_rx2RxCaFalling
  117      3        19       1        1        funcIntrFlexeOhRxChange_6_rx2RxCaRising
  118      3        20       1        1        funcIntrFlexeOhRxChange_6_rx2RxCrFalling
  119      3        21       1        1        funcIntrFlexeOhRxChange_6_rx2RxCrRising
  121      3        17       1        1        funcIntrFlexeOhRxChange_6_rx2RxRpfFalling
  122      3        16       1        1        funcIntrFlexeOhRxChange_6_rx2RxRpfRising

  7        0        24       1        1        funcIntrFlexeOhLock7
  15       0        16       1        1        funcIntrFlexeOhLockLos7
  23       0        9        1        1        funcIntrFlexeOhMfLock7
  31       0        0        1        1        funcIntrFlexeOhMfLockLos7
  129      3        31       1        1        funcIntrFlexeOhRxChange_7_rx2RxCaFalling
  130      4        0        1        1        funcIntrFlexeOhRxChange_7_rx2RxCaRising
  131      4        1        1        1        funcIntrFlexeOhRxChange_7_rx2RxCrFalling
  132      4        2        1        1        funcIntrFlexeOhRxChange_7_rx2RxCrRising
  134      3        30       1        1        funcIntrFlexeOhRxChange_7_rx2RxRpfFalling
  135      3        29       1        1        funcIntrFlexeOhRxChange_7_rx2RxRpfRising
*/
#define SYS_FLEXE_MGR_INTR_NUM    10
const sys_flexe_mgr_intr_t g_flexe_mgr_intr[SYS_FLEXE_MAX_INST_CNT*SYS_FLEXE_MGR_INTR_NUM] = 
{
    /* 
     ====================================================================
      Inst     Word     Bit      Intr_type
     -------------------------------------------------------------------- */
    { 0,       0,       31,      SYS_FLEXE_MGR_INTR_OHLOCK        },
    { 0,       0,       23,      SYS_FLEXE_MGR_INTR_OHLOCKLOS     },
    { 0,       0,       8 ,      SYS_FLEXE_MGR_INTR_OHMFLOCK      },
    { 0,       0,       7 ,      SYS_FLEXE_MGR_INTR_OHMFLOCKLOS   },
    { 0,       1,       4 ,      SYS_FLEXE_MGR_INTR_CA            },
    { 0,       1,       5 ,      SYS_FLEXE_MGR_INTR_CA            },
    { 0,       1,       6 ,      SYS_FLEXE_MGR_INTR_CR            },
    { 0,       1,       7 ,      SYS_FLEXE_MGR_INTR_CR            },
    { 0,       1,       3 ,      SYS_FLEXE_MGR_INTR_RPF_FALLING   },
    { 0,       1,       2 ,      SYS_FLEXE_MGR_INTR_RPF_RISING    },

    { 1,       0,       30,      SYS_FLEXE_MGR_INTR_OHLOCK        },
    { 1,       0,       22,      SYS_FLEXE_MGR_INTR_OHLOCKLOS     },
    { 1,       0,       15,      SYS_FLEXE_MGR_INTR_OHMFLOCK      },
    { 1,       0,       6 ,      SYS_FLEXE_MGR_INTR_OHMFLOCKLOS   },
    { 1,       1,       17,      SYS_FLEXE_MGR_INTR_CA            },
    { 1,       1,       18,      SYS_FLEXE_MGR_INTR_CA            },
    { 1,       1,       19,      SYS_FLEXE_MGR_INTR_CR            },
    { 1,       1,       20,      SYS_FLEXE_MGR_INTR_CR            },
    { 1,       1,       16,      SYS_FLEXE_MGR_INTR_RPF_FALLING   },
    { 1,       1,       15,      SYS_FLEXE_MGR_INTR_RPF_RISING    },

    { 2,       0,       29,      SYS_FLEXE_MGR_INTR_OHLOCK        },
    { 2,       0,       21,      SYS_FLEXE_MGR_INTR_OHLOCKLOS     },
    { 2,       0,       14,      SYS_FLEXE_MGR_INTR_OHMFLOCK      },
    { 2,       0,       5 ,      SYS_FLEXE_MGR_INTR_OHMFLOCKLOS   },
    { 2,       1,       30,      SYS_FLEXE_MGR_INTR_CA            },
    { 2,       1,       31,      SYS_FLEXE_MGR_INTR_CA            },
    { 2,       2,       0 ,      SYS_FLEXE_MGR_INTR_CR            },
    { 2,       2,       1 ,      SYS_FLEXE_MGR_INTR_CR            },
    { 2,       1,       29,      SYS_FLEXE_MGR_INTR_RPF_FALLING   },
    { 2,       1,       28,      SYS_FLEXE_MGR_INTR_RPF_RISING    },

    { 3,       0,       28,      SYS_FLEXE_MGR_INTR_OHLOCK        },
    { 3,       0,       20,      SYS_FLEXE_MGR_INTR_OHLOCKLOS     },
    { 3,       0,       13,      SYS_FLEXE_MGR_INTR_OHMFLOCK      }, 
    { 3,       0,       4 ,      SYS_FLEXE_MGR_INTR_OHMFLOCKLOS   },
    { 3,       2,       11,      SYS_FLEXE_MGR_INTR_CA            },
    { 3,       2,       12,      SYS_FLEXE_MGR_INTR_CA            },
    { 3,       2,       13,      SYS_FLEXE_MGR_INTR_CR            },
    { 3,       2,       14,      SYS_FLEXE_MGR_INTR_CR            },
    { 3,       2,       10,      SYS_FLEXE_MGR_INTR_RPF_FALLING   },
    { 3,       2,       9 ,      SYS_FLEXE_MGR_INTR_RPF_RISING    },

    { 4,       0,       27,      SYS_FLEXE_MGR_INTR_OHLOCK        },
    { 4,       0,       19,      SYS_FLEXE_MGR_INTR_OHLOCKLOS     },
    { 4,       0,       12,      SYS_FLEXE_MGR_INTR_OHMFLOCK      },
    { 4,       0,       3 ,      SYS_FLEXE_MGR_INTR_OHMFLOCKLOS   }, 
    { 4,       2,       24,      SYS_FLEXE_MGR_INTR_CA            },
    { 4,       2,       25,      SYS_FLEXE_MGR_INTR_CA            },
    { 4,       2,       26,      SYS_FLEXE_MGR_INTR_CR            },
    { 4,       2,       27,      SYS_FLEXE_MGR_INTR_CR            },
    { 4,       2,       23,      SYS_FLEXE_MGR_INTR_RPF_FALLING   },
    { 4,       2,       22,      SYS_FLEXE_MGR_INTR_RPF_RISING    },

    { 5,       0,       26,      SYS_FLEXE_MGR_INTR_OHLOCK        },
    { 5,       0,       18,      SYS_FLEXE_MGR_INTR_OHLOCKLOS     },
    { 5,       0,       11,      SYS_FLEXE_MGR_INTR_OHMFLOCK      },
    { 5,       0,       2 ,      SYS_FLEXE_MGR_INTR_OHMFLOCKLOS   },
    { 5,       3,       5 ,      SYS_FLEXE_MGR_INTR_CA            },
    { 5,       3,       6 ,      SYS_FLEXE_MGR_INTR_CA            },
    { 5,       3,       7 ,      SYS_FLEXE_MGR_INTR_CR            },
    { 5,       3,       8 ,      SYS_FLEXE_MGR_INTR_CR            },
    { 5,       3,       4 ,      SYS_FLEXE_MGR_INTR_RPF_FALLING   },
    { 5,       3,       3 ,      SYS_FLEXE_MGR_INTR_RPF_RISING    },

    { 6,       0,       25,      SYS_FLEXE_MGR_INTR_OHLOCK        },
    { 6,       0,       17,      SYS_FLEXE_MGR_INTR_OHLOCKLOS     },
    { 6,       0,       10,      SYS_FLEXE_MGR_INTR_OHMFLOCK      },
    { 6,       0,       1 ,      SYS_FLEXE_MGR_INTR_OHMFLOCKLOS   },
    { 6,       3,       18,      SYS_FLEXE_MGR_INTR_CA            },
    { 6,       3,       19,      SYS_FLEXE_MGR_INTR_CA            },
    { 6,       3,       20,      SYS_FLEXE_MGR_INTR_CR            },
    { 6,       3,       21,      SYS_FLEXE_MGR_INTR_CR            },
    { 6,       3,       17,      SYS_FLEXE_MGR_INTR_RPF_FALLING   },
    { 6,       3,       16,      SYS_FLEXE_MGR_INTR_RPF_RISING    },

    { 7,       0,       24,      SYS_FLEXE_MGR_INTR_OHLOCK        },
    { 7,       0,       16,      SYS_FLEXE_MGR_INTR_OHLOCKLOS     },
    { 7,       0,       9 ,      SYS_FLEXE_MGR_INTR_OHMFLOCK      },
    { 7,       0,       0 ,      SYS_FLEXE_MGR_INTR_OHMFLOCKLOS   },
    { 7,       3,       31,      SYS_FLEXE_MGR_INTR_CA            },
    { 7,       4,       0 ,      SYS_FLEXE_MGR_INTR_CA            },
    { 7,       4,       1 ,      SYS_FLEXE_MGR_INTR_CR            },
    { 7,       4,       2 ,      SYS_FLEXE_MGR_INTR_CR            },
    { 7,       3,       30,      SYS_FLEXE_MGR_INTR_RPF_FALLING   },
    { 7,       3,       29,      SYS_FLEXE_MGR_INTR_RPF_RISING    },
};

extern sal_file_t      g_flexe_dump_fp;
extern sal_file_t      g_tm_dump_fp;
extern const uint8     g_dmps_dbg_sw;

extern sys_datapath_master_t* p_usw_datapath_master[CTC_MAX_LOCAL_CHIP_NUM_PP];
extern const uint32 g_mcmac_mode_value_map[McMac_TOTAL_CNT][CTC_CHIP_MAX_SERDES_MODE];
extern const uint32 g_mcmac_fec_value_map[McMac_TOTAL_CNT][MAX_MODE_FEC];
extern const uint32 g_mode_with_fec_map[CTC_CHIP_MAX_SERDES_MODE][MAX_MODE_FEC];

/* internal */ 
STATIC int32
_sys_tmm_flexe_rx_c_handle(uint8 lchip, sys_flexe_group_t* group_node);
STATIC int32
_sys_tmm_flexe_get_enable(uint8 lchip, uint8 cs_id, uint8 *p_en);
STATIC int32
_sys_tmm_flexe_get_phy_lane_num(uint8 lchip, uint8 logical_serdes_id, uint8* p_lane_num);
STATIC void
_sys_tmm_flexe_check_value_legal(uint8 lchip, uint8 type, void *arg, void *value_to_be_checked, uint8 *legal);
STATIC int32
_sys_tmm_flexe_slot_shu2heng(uint8 lchip, sys_flexe_group_t *group_node, uint8 intlv_slot, uint8* p_nointlv_slot);
STATIC uint32
_sys_tmm_flexe_mac_get_eth_config_val(uint8 lchip, uint8 serdes_mode, uint8 fec_type, uint8 item);
STATIC int32
_sys_tmm_flexe_client_set_datapath_main(uint8 lchip, sys_flexe_client_t* client_node, uint8 enable);
STATIC int32
_sys_tmm_flexe_check_flexe_cs_used(uint8 lchip, uint8 cs_id, uint8 *p_cs_used);
STATIC int32
_sys_tmm_flexe_static_switch_lb(uint8 lchip, sys_flexe_group_t* group_node, uint32 val, uint8 is_normal);
STATIC int32
_sys_tmm_flexe_static_switch_manual(uint8 lchip, sys_flexe_group_t* group_node, uint32 val);
STATIC int32
_sys_tmm_flexe_client_unbind_port(uint8 lchip, sys_flexe_client_t** pp_client_node);
STATIC int32
_sys_tmm_flexe_client_bind_port(uint8 lchip, sys_flexe_client_t* client_node, uint32 gport);
STATIC int32
_sys_tmm_flexe_alarm_cr_timeout(uint8 lchip, uint32 group_id, uint8 cr_timeout);
STATIC int32
_sys_tmm_flexe_client_free_mac(uint8 lchip, sys_flexe_client_t *client_node);
STATIC int32
_sys_tmm_flexe_client_rx_slot_calc(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_client_t* client_node, uint8 act_flag, uint8 check_match, ctc_flexe_client_slot_t* p_client_slot);
STATIC int32
_sys_tmm_flexe_alarm_mismatch(uint8 lchip, uint8 inst_id, uint8 flexe_shim_id);
STATIC int32
_sys_tmm_flexe_send_cr_handle(uint8 lchip, sys_flexe_group_t* group_node);
STATIC int32
_sys_tmm_flexe_client_force_clear(uint8 lchip, sys_flexe_client_t* client_node, sys_flexe_dir_t dir);
STATIC int32
_sys_tmm_flexe_client_force_clear_switch(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_client_t* client_node, sys_flexe_dir_t dir);
STATIC int32
_sys_tmm_flexe_get_group_manual_table(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, uint32 *p_val);
int32
sys_tmm_flexe_get_client_link_up(uint8 lchip, uint32 client_id, uint8* p_is_up);

/* extern */
extern int32
_sys_tmm_mac_get_flexe_mac_en(uint8 lchip, uint16 mac_id, uint8 dir, uint8* p_enable);
extern int32
_sys_tmm_mac_set_internal_property(uint8 lchip, uint16 lport, ctc_port_property_t port_prop, uint32 value);
extern int32
_sys_tmm_dynamic_switch_datapath(uint8 lchip, sys_tmm_ds_target_attr_t *p_ds_attr);
extern int32
_sys_tmm_mac_set_mac_rx_en(uint8 lchip, uint16 mac_id, uint32 enable);
extern int32
_sys_tmm_mac_get_link_up(uint8 lchip, uint16 lport, uint32* p_is_up, uint32 is_port);
extern int32
_sys_tmm_mac_set_unidir_en(uint8 lchip, uint16 lport, uint8 enable, uint8 force_cfg);
extern int32
_sys_tmm_mac_set_ipg(uint8 lchip, uint16 lport, uint32 value_raw);
extern int32
sys_tmm_serdes_set_tx_en(uint8 lchip, uint8 serdes_id, uint8 enable);
extern int32 
_sys_tmm_datapath_common_calendar(int16 entry_num, uint32 count, uint32 *p_speed, uint8 *p_error, uint16 *p_walk_end, uint16 *p_cal);
extern uint32
_sys_tmm_nettx_speed_to_credit(uint16 speed);
extern uint32
_sys_tmm_dynamic_switch_q_flush(uint8 lchip, sys_tmm_ds_target_attr_t *p_ds_attr);
extern int32 
sys_tmm_serdes_get_glb_info(uint8 lchip, uint8 physic_serdes_id, sys_tmm_serdes_glb_info_type_t type, uint8 *value);
extern int32
_sys_tmm_mac_set_flexe_mac_en(uint8 lchip, uint16 mac_id, uint8 dir, uint8 enable);
extern int32
_sys_tmm_datapath_clear_port_attr(uint8 lchip, uint16 lport);
extern int32
_sys_tmm_mac_intr_get_flexe_table_bitmap(uint8 lchip, sys_datapath_lport_attr_t* port_attr, uint32* tb_id, uint32* tb_index, uint32* value);
extern int32
_sys_tmm_mac_get_pcs_link_status(uint8 lchip, uint16 lport, uint32* p_is_up);
extern int32
sys_tmm_mc_mac_pcs_rx_rst(uint8 lchip, uint16 lport, sys_datapath_lport_attr_t* port_attr, uint8 reset);
extern int32
_sys_tmm_datapath_set_internal_loopback_pcs(uint8 lchip, uint8 physic_serdes_id, uint8 enable);
extern int32
_sys_tmm_mac_set_link_intr(uint8 lchip, uint16 lport, uint32 enable);
extern int32
_sys_tmm_mac_get_link_intr(uint8 lchip, uint16 lport, uint32* enable);
extern int32
_sys_tmm_mac_set_tx_force_fault_by_mac_id(uint8 lchip, uint16 mac_id, uint32 fault_bmp);
extern int32
_sys_tmm_mac_set_mac_config(uint8 lchip,
                            uint16 lport,
                            ctc_chip_serdes_mode_t mode,
                            ctc_port_fec_type_t fec_type,
                            sys_dmps_lport_type_t port_type,
                            uint8 is_init);
extern void
_ctc_tmm_dkit_check_abnormal_intr(uint8 lchip, uint8 op);


/****************************************************************************
 *
* Function
*
*****************************************************************************/

#define ____FLEXE_LIB____

/*
  Description: Lookup group node by group_id
  return:
      group_node if found.
      NULL if fail
 */
STATIC int32
_sys_tmm_flexe_group_lookup(uint8 lchip, uint32 group_id, sys_flexe_group_t** pp_group)
{
    sys_flexe_group_t* p_group = NULL;
    ctc_slistnode_t* node = NULL;

    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->group_list, node)
    {
        p_group = _ctc_container_of(node, sys_flexe_group_t, head);
        if (p_group->group_id == group_id)
        {
            *pp_group = p_group;
            break;
        }
    }

    return CTC_E_NONE;
}

/*
  Description: Lookup group node by Logical SerDes, or check whether PHY(identified by Logical SerDes) binded to group
  return:
      group_node if found.
      NULL if fail
 */
STATIC sys_flexe_group_t*
_sys_tmm_flexe_group_lookup_by_serdes(uint8 lchip, uint8 logical_serdes_id)
{
    uint8 i                   = 0;
    uint8 phy_lane_num        = 0;
    uint8 logical_serdes_base = 0;
    ctc_slistnode_t* node     = NULL;
    sys_flexe_group_t* tmp_group_node = NULL;

    _sys_tmm_flexe_get_phy_lane_num(lchip, logical_serdes_id, &phy_lane_num);
    if (0 == phy_lane_num)
    {
        return NULL;
    }

    logical_serdes_base = logical_serdes_id / phy_lane_num * phy_lane_num;

    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->group_list, node)
    {
        tmp_group_node = _ctc_container_of(node, sys_flexe_group_t, head);
        SYS_CONDITION_CONTINUE(!tmp_group_node || !tmp_group_node->phy_cnt);
        SYS_CONDITION_CONTINUE(NULL == tmp_group_node->phy_list);
        for (i = 0; i < tmp_group_node->phy_cnt; i++)
        { 
            if (tmp_group_node->phy_list[i].logical_serdes_base == logical_serdes_base)
            {
                return tmp_group_node;
            }
        }
    }

    return NULL;
}

/*
  Description: Lookup group node by flexe_shim_id+instance, or check whether the specified instance is free or not
  return:
      group_node if found.
      NULL if fail
 */
STATIC sys_flexe_group_t*
_sys_tmm_flexe_group_lookup_by_inst(uint8 lchip, uint8 flexe_shim_id, uint8 asic_inst)
{
    uint8 i = 0;
    sys_flexe_group_t* group_node = NULL;
    ctc_slistnode_t* node = NULL;

    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->group_list, node)
    {
        group_node = _ctc_container_of(node, sys_flexe_group_t, head);
        SYS_CONDITION_CONTINUE(!group_node);
        SYS_CONDITION_CONTINUE(flexe_shim_id != group_node->flexe_shim_id);
        for (i = 0; i < group_node->inst_cnt; i++)
        {
            if (asic_inst == group_node->inst_list[i])
            {
                return group_node;
            }
        }
    }

    return NULL;
}

/*
  Description: Lookup client node by client_id
  return:
      client_node if found.
      NULL if fail
 */
STATIC int32
_sys_tmm_flexe_client_lookup(uint8 lchip, uint32 client_id, sys_flexe_client_t** pp_client)
{
    sys_flexe_client_t* p_client = NULL;
    ctc_slistnode_t* node = NULL;

    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
    {
        p_client = _ctc_container_of(node, sys_flexe_client_t, head);
        if (p_client->client_id == client_id)
        {
            *pp_client = p_client;
            break;
        }
    }

    return CTC_E_NONE;
}

/*
  Description: Lookup client node by mac id
  return:
      client_node if found.
      NULL if fail
 */
int32
_sys_tmm_flexe_client_lookup_by_mac(uint8 lchip, uint16 mac_id, sys_flexe_client_t** pp_client)
{
    sys_flexe_client_t* p_client = NULL;
    ctc_slistnode_t* node = NULL;

    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
    {
        p_client = _ctc_container_of(node, sys_flexe_client_t, head);
        if (p_client->mac_id == mac_id)
        {
            *pp_client = p_client;
            break;
        }
    }

    return CTC_E_NONE;
}

/*
  Description: Lookup client node by flexe shim channel id, or check whether the specified shim_chid is free or not
  return:
      client_node if found.
      NULL if fail
 */
STATIC int32
_sys_tmm_flexe_client_lookup_by_xc_chid(uint8 lchip, uint8 flexe_shim_id, uint8 xc_chid, sys_flexe_client_t** pp_client)
{
    sys_flexe_client_t* p_client = NULL;
    ctc_slistnode_t* node = NULL;

    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
    {
        p_client = _ctc_container_of(node, sys_flexe_client_t, head);
        if ((p_client->flexe_shim_id == flexe_shim_id) && (p_client->tx_xc_chid == xc_chid))
        {
            *pp_client = p_client;
            break;
        }
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_inst_used(uint8 lchip, uint8 flexe_shim_id, uint8 inst, uint8 *p_used)
{
    sys_flexe_group_t *tmp_group_node = NULL;
    if (p_used)
    {
        tmp_group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, flexe_shim_id, inst);
        *p_used = tmp_group_node ? 1 : 0;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_free_xc_chid(uint8 lchip, uint8 flexe_shim_id, uint8* p_xc_chid)
{
    uint8 i = 0;
    sys_flexe_client_t* p_client = NULL;

    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CLIENT); i++)
    {
        p_client = NULL;
        _sys_tmm_flexe_client_lookup_by_xc_chid(lchip, flexe_shim_id, i, &p_client);
        if (NULL == p_client)
        {
            *p_xc_chid = i;
            break;
        }
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_group_phy_speed(uint8 lchip, sys_flexe_group_t *group_node, uint8 *speed_mode)
{
    if (!group_node->phy_cnt || !speed_mode)
    {
        return CTC_E_NONE;
    }
    SYS_FLEXE_MODE_2_SPEED(group_node->phy_list[0].pcs_mode, *speed_mode);

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_phy_ifmode(uint8 lchip, sys_datapath_serdes_info_t* p_serdes, uint32* p_speed, uint32* p_iftype)
{
    uint32 speed = 0;
    uint32 iftype = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;

    port_attr = sys_usw_datapath_get_port_capability(lchip, p_serdes->lport);
    if (!port_attr)
    {
        speed  = CTC_PORT_SPEED_MAX;
        iftype = CTC_PORT_IF_MAX_TYPE;
    }
    else
    {
        speed  = port_attr->speed_mode;
        iftype = port_attr->interface_type;
        if ((CTC_CHIP_SERDES_LG_MODE != p_serdes->mode)
            && (CTC_CHIP_SERDES_LG_R1_MODE != p_serdes->mode)
            && (CTC_CHIP_SERDES_CG_MODE != p_serdes->mode)
            && (CTC_CHIP_SERDES_CG_R2_MODE != p_serdes->mode)
            && (CTC_CHIP_SERDES_CCG_R4_MODE != p_serdes->mode)
            && (CTC_CHIP_SERDES_CDG_R8_MODE != p_serdes->mode))
        {
            speed  = CTC_PORT_SPEED_MAX;
            iftype = CTC_PORT_IF_MAX_TYPE;
        }
        if ((CTC_PORT_SPEED_50G != speed)
            && (CTC_PORT_SPEED_100G != speed)
            && (CTC_PORT_SPEED_200G != speed)
            && (CTC_PORT_SPEED_400G != speed))
        {
            speed  = CTC_PORT_SPEED_MAX;
            iftype = CTC_PORT_IF_MAX_TYPE;
        }
    }

    if (p_speed)
    {
        *p_speed = speed;
    }
    if (p_iftype)
    {
        *p_iftype = iftype;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_phy_lane_num(uint8 lchip, uint8 logical_serdes_id, uint8* p_lane_num)
{
    sys_datapath_serdes_info_t* p_serdes = NULL;
    CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, logical_serdes_id, &p_serdes));
    if (p_lane_num)
    {
        SYS_FLEXE_MODE_2_LANE_NUM(p_serdes->mode, *p_lane_num);
    }

    return CTC_E_NONE;
}

/*
  Description: get client slot cnt with specified dir/sw_act_flag, as is:
      TX active slot cnt
      RX active slot cnt
      TX inactive slot cnt
      RX inactive slot cnt
      then can calculate speed value with the same condtion.
  return:
      slot cnt
 */
int32
_sys_tmm_flexe_get_client_slot_cnt(uint8 lchip, sys_flexe_client_t *client_node, uint8 dir, uint8 act_flag, uint8 *p_cnt)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 slot_cnt = 0;
    uint8 cfg_condition   = FALSE;
    uint8 act_condition   = FALSE;
    uint8 inact_condition = FALSE;
    sys_flexe_group_t *group_node = NULL;
    sys_flexe_group_dir_t *p_dir = NULL;

    SYS_CONDITION_RETURN(!p_cnt, CTC_E_NONE);
    _sys_tmm_flexe_group_lookup(lchip, client_node->group_id, &group_node);
    if (!group_node)
    {
        *p_cnt = 0;
        return CTC_E_NONE;
    }

    p_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            cfg_condition = (SYS_FLEXE_CFG_FLAG == act_flag) && (p_dir->dir_inst[i].slot_cfg_shim_chid[j] == client_node->shim_chid);
            act_condition = (SYS_FLEXE_ACTIVE_FLAG == act_flag) && \
                (((SYS_FLEXE_ACTIVE_A == p_dir->active) && (p_dir->dir_inst[i].switch_shim_chid_a[j] == client_node->shim_chid)) \
                    || ((SYS_FLEXE_ACTIVE_B == p_dir->active) && (p_dir->dir_inst[i].switch_shim_chid_b[j] == client_node->shim_chid)));
            inact_condition = (SYS_FLEXE_INACTIVE_FLAG == act_flag) && \
                (((SYS_FLEXE_ACTIVE_A == p_dir->active) && (p_dir->dir_inst[i].switch_shim_chid_b[j] == client_node->shim_chid)) \
                    || ((SYS_FLEXE_ACTIVE_B == p_dir->active) && (p_dir->dir_inst[i].switch_shim_chid_a[j] == client_node->shim_chid)));

            if (cfg_condition || act_condition || inact_condition)
            {
                slot_cnt++;
            }
        }
    }
    *p_cnt = slot_cnt;

    return CTC_E_NONE;
}

/*
  Description: get client slot cnt with specified dir/hw_act_flag, as is:
      TX active slot cnt
      RX active slot cnt
      TX inactive slot cnt
      RX inactive slot cnt
      then can calculate speed value with the same condtion.
  return:
      slot cnt
 */
int32
_sys_tmm_flexe_get_hw_client_slot_cnt(uint8 lchip, sys_flexe_client_t *client_node, uint8 dir, uint8 act_flag, uint8 *p_cnt)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 slot_cnt = 0;
    uint8 cfg_condition   = FALSE;
    uint8 act_condition   = FALSE;
    uint8 inact_condition = FALSE;
    uint32 hw_table = 0;
    sys_flexe_group_t *group_node = NULL;
    sys_flexe_group_dir_t *p_dir = NULL;

    SYS_CONDITION_RETURN(!p_cnt, CTC_E_NONE);
    _sys_tmm_flexe_group_lookup(lchip, client_node->group_id, &group_node);
    if (!group_node)
    {
        *p_cnt = 0;
        return CTC_E_NONE;
    }

    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_manual_table(lchip, group_node, dir, &hw_table));

    p_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            cfg_condition = (SYS_FLEXE_CFG_FLAG == act_flag) && (p_dir->dir_inst[i].slot_cfg_shim_chid[j] == client_node->shim_chid);
            act_condition = (SYS_FLEXE_ACTIVE_FLAG == act_flag) && \
                (((SYS_FLEXE_ACTIVE_A == hw_table) && (p_dir->dir_inst[i].switch_shim_chid_a[j] == client_node->shim_chid)) \
                    || ((SYS_FLEXE_ACTIVE_B == hw_table) && (p_dir->dir_inst[i].switch_shim_chid_b[j] == client_node->shim_chid)));
            inact_condition = (SYS_FLEXE_INACTIVE_FLAG == act_flag) && \
                (((SYS_FLEXE_ACTIVE_A == hw_table) && (p_dir->dir_inst[i].switch_shim_chid_b[j] == client_node->shim_chid)) \
                    || ((SYS_FLEXE_ACTIVE_B == hw_table) && (p_dir->dir_inst[i].switch_shim_chid_a[j] == client_node->shim_chid)));

            if (cfg_condition || act_condition || inact_condition)
            {
                slot_cnt++;
            }
        }
    }
    *p_cnt = slot_cnt;

    return CTC_E_NONE;
}

/*
  Description: get client speed with specified dir/act_flag, as is:
      TX active speed
      RX active speed
      TX inactive speed
      RX inactive speed
  return:
      speed value
 */

STATIC int32
_sys_tmm_flexe_get_client_speed_val(uint8 lchip, sys_flexe_client_t* client_node, sys_flexe_dir_t dir, uint8 act_flag, uint32 *p_speed_value)
{
    uint8 slot_cnt = 0;

    if (p_speed_value)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_get_client_slot_cnt(lchip, client_node, dir, act_flag, &slot_cnt));
        *p_speed_value = slot_cnt * SYS_FLEXE_SLOT_SPEED;
    }

    return CTC_E_NONE;
}

/*
  Description: check speficied dir have slot cnt or not
  return:
      slot_cnt
 */
STATIC int32
_sys_tmm_flexe_check_client_slot(uint8 lchip, sys_flexe_client_t* client_node, uint8 dir, uint8* have)
{
    uint8 cfg_cnt        = 0;
    uint8 active_cnt     = 0;
    uint8 inactive_cnt   = 0;

    if (!have)
    {
        return CTC_E_NONE;
    }

    *have = 0;
    _sys_tmm_flexe_get_client_slot_cnt(lchip, client_node, dir, SYS_FLEXE_CFG_FLAG,      &cfg_cnt);
    _sys_tmm_flexe_get_client_slot_cnt(lchip, client_node, dir, SYS_FLEXE_ACTIVE_FLAG,   &active_cnt);
    _sys_tmm_flexe_get_client_slot_cnt(lchip, client_node, dir, SYS_FLEXE_INACTIVE_FLAG, &inactive_cnt);
    if (cfg_cnt || active_cnt || inactive_cnt)
    {
        *have = 1;
    }

    return CTC_E_NONE;
}

/*
  Description: get asic instance id (0~7) list by specified phy(identified with Logic SerDes)
  return:
      8-bit map with instance id (0~7) list 
 */
STATIC void
_sys_tmm_flexe_get_inst_bmp_by_serdes(uint8 lchip, sys_flexe_group_t *group_node, uint8 logical_serdes_id, uint8 *p_inst_bmp)
{
    uint8 i                = 0;
    uint8 j                = 0;
    uint8 phy_speed        = 0;
    uint8 phy_inst_cnt = 0;

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &phy_speed);
    phy_inst_cnt = SYS_TMM_FLEXE_PHY_2_INST_CNT(phy_speed);
    for (i = 0; i < group_node->phy_cnt; i++)
    {
        if (logical_serdes_id == group_node->phy_list[i].logical_serdes_base)
        {
            FLEXE_DBG_PRINTF("Hit logical_serdes_id %d\n", logical_serdes_id);
            FLEXE_DBG_PRINTF("group %d flexe shim id %d, inst list:\n", group_node->group_id, group_node->flexe_shim_id);
            for (j = 0; j < phy_inst_cnt; j++)
            {
                /* all instances within one phy are continuable */
                *p_inst_bmp |= (1 << (group_node->phy_list[i].inst_base+j));
            }
            FLEXE_DBG_PRINTF("\n");
            break;
        }
    }
}

sys_flexe_phy_t*
_sys_tmm_flexe_get_phy_node(uint8 lchip, uint8 logical_serdes_id)
{
    uint8 i = 0;
    uint8 phy_lane_num = 0;
    int32 ret = CTC_E_NONE;
    uint8 logical_serdes_base = 0;
    sys_flexe_group_t*  group_node  = NULL;
    sys_flexe_phy_t*    phy_node = NULL;
    sys_datapath_serdes_info_t* p_serdes = NULL;

    group_node = _sys_tmm_flexe_group_lookup_by_serdes(lchip, logical_serdes_id);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] phy %d has not added to any FlexE group!\n", logical_serdes_id);
        return NULL;
    }

    ret = sys_usw_datapath_get_serdes_info(lchip, logical_serdes_id, &p_serdes);
    SYS_CONDITION_RETURN((0 != ret), NULL);

    SYS_FLEXE_MODE_2_LANE_NUM(p_serdes->mode, phy_lane_num);
    SYS_CONDITION_RETURN(!phy_lane_num, NULL);

    logical_serdes_base = logical_serdes_id / phy_lane_num * phy_lane_num;

    for (i = 0; i < group_node->phy_cnt; i++)
    {
        if (group_node->phy_list[i].logical_serdes_base == logical_serdes_base)
        {
            phy_node = &group_node->phy_list[i];
            break;
        }
    }

    return phy_node;
}

STATIC sys_flexe_phy_t*
_sys_tmm_flexe_phy_lookup_by_inst(uint8 lchip, uint8 flexe_shim_id, uint8 inst_id)
{
    uint8  i            = 0;
    uint8  phy_speed    = 0;
    uint8  phy_inst_cnt = 0;
    sys_flexe_group_t *group_node = NULL;
    sys_flexe_phy_t   *phy_node   = NULL;

    group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, flexe_shim_id, inst_id);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] DP %d inst %d has not added to any FlexE group!\n", flexe_shim_id, inst_id);    
        return NULL;
    }

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &phy_speed);
    phy_inst_cnt = SYS_TMM_FLEXE_PHY_2_INST_CNT(phy_speed);

    for (i = 0; i < group_node->phy_cnt; i++)
    {
        if (group_node->phy_list[i].inst_base == inst_id / phy_inst_cnt * phy_inst_cnt)
        {
            phy_node = &group_node->phy_list[i];
            break;
        }
    }

    return phy_node;
}

/*
  Description: scan and return continuous free instance list for PHY
  return:
      continuous instance list(only return the lowest one)
 */
STATIC int32
_sys_tmm_flexe_get_free_instlist(uint8 lchip, uint8 flexe_shim_id, uint8 cont_num, uint8 *inst_base)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 used = 0;

    if (!inst_base)
    {
        return CTC_E_NONE;
    }
    else
    {
        *inst_base = SYS_FLEXE_UNUSED_FLAG_U8;
    }

    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        SYS_CONDITION_CONTINUE(i % cont_num);
        for (j = i; j < cont_num+i; j++)
        {
            _sys_tmm_flexe_check_inst_used(lchip, flexe_shim_id, j, &used);
            if (used)
            {
                break;
            }
        }
        if (j == (cont_num+i)) /* all cont_num instnaces are free */
        {
            *inst_base = i;
            break;
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_inst_number_pos(uint8 lchip, uint8 flexe_shim_id, uint8 inst_id, uint8 *p_pos)
{
    uint8  phy_speed    = 0;
    uint8  phy_inst_cnt = 0;
    sys_flexe_group_t *group_node = NULL;

    SYS_CONDITION_RETURN(!p_pos, CTC_E_NONE);
    *p_pos = SYS_FLEXE_UNUSED_FLAG_U8;

    group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, flexe_shim_id, inst_id);
    SYS_CONDITION_RETURN(!group_node, CTC_E_NONE);

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &phy_speed);
    phy_inst_cnt = SYS_TMM_FLEXE_PHY_2_INST_CNT(phy_speed);
    SYS_CONDITION_RETURN(!phy_inst_cnt, CTC_E_NONE);
    SYS_CONDITION_RETURN(((CTC_PORT_SPEED_50G!=phy_speed) && (inst_id%2)), CTC_E_NONE);

    if (CTC_PORT_SPEED_400G == phy_speed)
    {
        /* 
         inst_id 0 -- phy_inst_number[0] 
         inst_id 2 -- phy_inst_number[1]
         inst_id 4 -- phy_inst_number[2]
         inst_id 6 -- phy_inst_number[3]
         */
        *p_pos = inst_id / 2;
    }
    else if (CTC_PORT_SPEED_200G == phy_speed)
    {
        /* 
         inst_id 0/4 -- phy_inst_number[0] 
         inst_id 2/6 -- phy_inst_number[1]
         */
        *p_pos = inst_id % 4 / 2;
    }
    else
    {
        /* 
         100G:
             inst_id 0/2/4/6 -- phy_inst_number[0] 
         50G:
             inst_id 0/1/2/3/4/5/6/7 -- phy_inst_number[0] 
         */
        *p_pos = 0;
    }

    return CTC_E_NONE;
}

/*
  Description: get instance number(within overhead) value for specified instance, only if instance is used by group
  return:
      instance number
 */
STATIC int32
_sys_tmm_flexe_get_inst_number(uint8 lchip, uint8 flexe_shim_id, uint8 inst_id, uint32 *p_val32)
{
    uint8  i            = 0;
    uint8  phy_speed    = 0;
    uint8  phy_inst_cnt = 0;
    //uint8  oh_inst_cnt  = 0;
    uint32 shft         = 0;
    uint8  oh_phy_inst_pos = 0;
    sys_flexe_group_t *group_node = NULL;

    SYS_CONDITION_RETURN(!p_val32, CTC_E_NONE);
    *p_val32 = 0;  /* default illegal value */

    group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, flexe_shim_id, inst_id);
    SYS_CONDITION_RETURN(!group_node, CTC_E_NONE);

    _sys_tmm_flexe_get_inst_number_pos(lchip, flexe_shim_id, inst_id, &oh_phy_inst_pos);
    SYS_CONDITION_RETURN((SYS_FLEXE_UNUSED_FLAG_U8 == oh_phy_inst_pos), CTC_E_NONE);

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &phy_speed);
    phy_inst_cnt = SYS_TMM_FLEXE_PHY_2_INST_CNT(phy_speed);
    //oh_inst_cnt = (CTC_PORT_SPEED_400G == phy_speed) ? 4 : ((CTC_PORT_SPEED_200G == phy_speed) ? 2 : 1);
    shft        = (CTC_PORT_SPEED_400G == phy_speed) ? 2 : ((CTC_PORT_SPEED_200G == phy_speed) ? 1 : 0);
    for (i = 0; i < group_node->phy_cnt; i++)
    {
        if (group_node->phy_list[i].inst_base == inst_id / phy_inst_cnt * phy_inst_cnt)
        {
            *p_val32 = (group_node->phy_list[i].phy_number << shft) | oh_phy_inst_pos;
            return CTC_E_NONE;
        }
    }

    return CTC_E_NONE;
}

/*
  Description: get TX/RX asic slot array by DS with tx/rx cfg/active slot, it shows how asic stores the slot, value is client_number
  return:
      2*dimentional array
          row: 8*instance at most
          column: 10*slot at most
 */
STATIC int32
_sys_tmm_flexe_get_group_asic_slot(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, uint8 act_flag, uint32 p_val[8][10])
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 asic_inst = 0;
    uint8 tmp_shim_chid = 0;
    uint8 xc_chid = 0;

    sys_flexe_client_t* tmp_client_node = NULL;

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        asic_inst = group_node->inst_list[i];
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            if (SYS_FLEXE_DIR_TX == dir)
            {
                if (SYS_FLEXE_CFG_FLAG == act_flag)
                {
                    tmp_shim_chid = group_node->tx.dir_inst[i].slot_cfg_shim_chid[j];
                }
                else if (SYS_FLEXE_ACTIVE_A == act_flag)
                {
                    tmp_shim_chid = group_node->tx.dir_inst[i].switch_shim_chid_a[j];
                }
                else
                {
                    tmp_shim_chid = group_node->tx.dir_inst[i].switch_shim_chid_b[j];
                }
            }
            else
            {
                if (SYS_FLEXE_CFG_FLAG == act_flag)
                {
                    tmp_shim_chid = group_node->rx.dir_inst[i].slot_cfg_shim_chid[j];
                }
                else if (SYS_FLEXE_ACTIVE_A == act_flag)
                {
                    tmp_shim_chid = group_node->rx.dir_inst[i].switch_shim_chid_a[j];
                }
                else
                {
                    tmp_shim_chid = group_node->rx.dir_inst[i].switch_shim_chid_b[j];
                }
            }
            if (0 == tmp_shim_chid)
            {
                p_val[asic_inst][j] = 0;
            }
            else
            {
                xc_chid = SYS_TMM_FLEXE_CLIENT_SHIM_2_XC_CHID(tmp_shim_chid);
                _sys_tmm_flexe_client_lookup_by_xc_chid(lchip, group_node->flexe_shim_id, xc_chid, &tmp_client_node);
                p_val[asic_inst][j] = tmp_client_node->client_number;
            }
        }
    }

    return CTC_E_NONE;
}

/*
  Description: get TX/RX client calendar array by DS with tx/rx cfg/active slot
  return:
      2*dimentional array
          row: 8*instance at most
          column: 20*slot at most
 */
STATIC int32
_sys_tmm_flexe_get_group_client_cal(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, uint8 act_flag, uint32 p_val[8][20])
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 slot_shu = 0;
    uint8 slot_heng = 0;
    uint8 slot_per_inst = 0;
    uint8 speed_mode = 0;
    uint8 asic_inst = 0;
    uint8 tmp_shim_chid = 0;
    uint8 xc_chid = 0;

    sys_flexe_client_t* tmp_client_node = NULL;

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            if (SYS_FLEXE_DIR_TX == dir)
            {
                if (SYS_FLEXE_CFG_FLAG == act_flag)
                {
                    tmp_shim_chid = group_node->tx.dir_inst[i].slot_cfg_shim_chid[j];
                }
                else if (SYS_FLEXE_ACTIVE_FLAG == act_flag)
                {
                    tmp_shim_chid = (SYS_FLEXE_ACTIVE_A == group_node->tx.active) ? group_node->tx.dir_inst[i].switch_shim_chid_a[j] : \
                        group_node->tx.dir_inst[i].switch_shim_chid_b[j];
                }
                else
                {
                    tmp_shim_chid = (SYS_FLEXE_ACTIVE_A == group_node->tx.active) ? group_node->tx.dir_inst[i].switch_shim_chid_b[j] : \
                        group_node->tx.dir_inst[i].switch_shim_chid_a[j];
                }
            }
            else
            {
                if (SYS_FLEXE_CFG_FLAG == act_flag)
                {
                    tmp_shim_chid = group_node->rx.dir_inst[i].slot_cfg_shim_chid[j];
                }
                else if (SYS_FLEXE_ACTIVE_FLAG == act_flag)
                {
                    tmp_shim_chid = (SYS_FLEXE_ACTIVE_A == group_node->rx.active) ? group_node->rx.dir_inst[i].switch_shim_chid_a[j] : \
                        group_node->rx.dir_inst[i].switch_shim_chid_b[j];
                }
                else
                {
                    tmp_shim_chid = (SYS_FLEXE_ACTIVE_A == group_node->rx.active) ? group_node->rx.dir_inst[i].switch_shim_chid_b[j] : \
                        group_node->rx.dir_inst[i].switch_shim_chid_a[j];
                }
            }

            if (CTC_PORT_SPEED_50G == speed_mode)
            {
                asic_inst = group_node->inst_list[i];
                slot_per_inst = j;
            }
            else
            {
                slot_shu = group_node->inst_list[i] * MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) + j;
                (void)_sys_tmm_flexe_slot_shu2heng(lchip, group_node, slot_shu, &slot_heng);
                asic_inst = group_node->inst_list[i] / 2 * 2;
                slot_per_inst = slot_heng % SYS_FLEXE_OH_MAX_SLOT_PER_INST;
            }

            if (0 == tmp_shim_chid)
            {
                p_val[asic_inst][slot_per_inst] = 0;
            }
            else
            {
                xc_chid = SYS_TMM_FLEXE_CLIENT_SHIM_2_XC_CHID(tmp_shim_chid);
                _sys_tmm_flexe_client_lookup_by_xc_chid(lchip, group_node->flexe_shim_id, xc_chid, &tmp_client_node);
                p_val[asic_inst][slot_per_inst] = tmp_client_node->client_number;
            }
        }
    }

    return CTC_E_NONE;
}

/*
  Description: get TX/RX client slot array by DS with tx/rx cfg/active slot
  return:
      2*dimentional array
          row: 8*instance at most
          column: 10*slot at most
 */
STATIC int32
_sys_tmm_flexe_get_hw_client_slot(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_client_t* client_node, sys_flexe_dir_t dir, uint8 act_flag, uint32 p_val[8][10])
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 shim_chid = 0;
    uint32 hw_table = 0;

    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_manual_table(lchip, group_node, SYS_FLEXE_DIR_RX, &hw_table));

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            if (SYS_FLEXE_DIR_TX == dir)
            {
                if (SYS_FLEXE_CFG_FLAG == act_flag)
                {
                    shim_chid = group_node->tx.dir_inst[i].slot_cfg_shim_chid[j];
                }
                else if (SYS_FLEXE_ACTIVE_FLAG == act_flag)
                {
                    shim_chid = (SYS_FLEXE_ACTIVE_A == hw_table) ? group_node->tx.dir_inst[i].switch_shim_chid_a[j] : \
                        group_node->tx.dir_inst[i].switch_shim_chid_b[j];
                }
                else
                {
                    shim_chid = (SYS_FLEXE_ACTIVE_A == hw_table) ? group_node->tx.dir_inst[i].switch_shim_chid_b[j] : \
                        group_node->tx.dir_inst[i].switch_shim_chid_a[j];
                }
            }
            else
            {
                if (SYS_FLEXE_CFG_FLAG == act_flag)
                {
                    shim_chid = group_node->rx.dir_inst[i].slot_cfg_shim_chid[j];
                }
                else if (SYS_FLEXE_ACTIVE_FLAG == act_flag)
                {
                    shim_chid = (SYS_FLEXE_ACTIVE_A == hw_table) ? group_node->rx.dir_inst[i].switch_shim_chid_a[j] : \
                        group_node->rx.dir_inst[i].switch_shim_chid_b[j];
                }
                else
                {
                    shim_chid = (SYS_FLEXE_ACTIVE_A == hw_table) ? group_node->rx.dir_inst[i].switch_shim_chid_b[j] : \
                        group_node->rx.dir_inst[i].switch_shim_chid_a[j];
                }
            }
            p_val[group_node->inst_list[i]][j] = ((shim_chid == client_node->shim_chid) ? 1 :0);
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_slot_shu2heng(uint8 lchip, sys_flexe_group_t *group_node, uint8 intlv_slot, uint8* p_nointlv_slot)
{
    uint8 nointlv_slot = 0;
    uint8 speed_mode = 0;

    nointlv_slot = intlv_slot;

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);
    if (CTC_PORT_SPEED_50G != speed_mode)
    {
        nointlv_slot = intlv_slot % SYS_FLEXE_INSTANCE_SLOT_100G_NUM;
        nointlv_slot = nointlv_slot % SYS_FLEXE_INSTANCE_SLOT_50G_NUM * 2 + nointlv_slot / SYS_FLEXE_INSTANCE_SLOT_50G_NUM;
        nointlv_slot += intlv_slot / SYS_FLEXE_INSTANCE_SLOT_100G_NUM * SYS_FLEXE_INSTANCE_SLOT_100G_NUM;
    }

    if (p_nointlv_slot)
    {
        *p_nointlv_slot = nointlv_slot;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_slot_heng2shu(uint8 lchip, sys_flexe_group_t *group_node,         uint8 nointlv_slot, uint8* p_intlv_slot)
{
    uint8 intlv_slot = 0;
    uint8 speed_mode = 0; 

    intlv_slot = nointlv_slot;

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);
    if (CTC_PORT_SPEED_50G != speed_mode)
    {
        intlv_slot = nointlv_slot % SYS_FLEXE_INSTANCE_SLOT_100G_NUM;
        intlv_slot = intlv_slot % 2 * SYS_FLEXE_INSTANCE_SLOT_50G_NUM + intlv_slot / 2;
        intlv_slot += nointlv_slot / SYS_FLEXE_INSTANCE_SLOT_100G_NUM * SYS_FLEXE_INSTANCE_SLOT_100G_NUM;
    }

    if (p_intlv_slot)
    {
        *p_intlv_slot = intlv_slot;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_cc_by_cycle_value(uint8 lchip, sys_flexe_group_t *group_node, uint8 cycle_value, sys_flexe_dir_t dir, uint8* p_cc)
{
    uint8 i = 0;
    sys_flexe_group_dir_t *p_group_dir = NULL;

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); i++)
    {
        if (cycle_value == p_group_dir->cc[i].cycle_value)
        {
            *p_cc = i;
            return CTC_E_NONE;
        }
    }

    return CTC_E_NOT_EXIST;
}

STATIC int32
_sys_tmm_flexe_get_group_inst_offset_by_asic_inst(uint8 lchip, sys_flexe_group_t *group_node, uint8 asic_inst, uint8* p_group_inst_offset)
{
    uint8 i = 0;

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        if (asic_inst == group_node->inst_list[i])
        {
            *p_group_inst_offset = i;
            return CTC_E_NONE;
        }
    }

    return CTC_E_NOT_EXIST;
}

/*
  Description: get instance offset in a phy, the offset is calculated by FlexE agreemengt:
  return:
      inst_offset in a phy
 */
STATIC int32
_sys_tmm_flexe_get_phy_instance_offset(uint8 lchip, sys_flexe_phy_t* phy_node, uint8 asic_inst, uint32 *p_inst_offset)
{
    switch (phy_node->pcs_mode)
    {
        case CTC_CHIP_SERDES_LG_R1_MODE:
        case CTC_CHIP_SERDES_LG_MODE:
        case CTC_CHIP_SERDES_CG_R2_MODE:
        case CTC_CHIP_SERDES_CG_MODE:
            *p_inst_offset = 0;
            break;
        case CTC_CHIP_SERDES_CCG_R4_MODE:
        case CTC_CHIP_SERDES_CDG_R8_MODE:
            *p_inst_offset = (asic_inst - phy_node->inst_base) / 2;
            break;
        default:
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] Unsupported PCS mode %d \n", phy_node->pcs_mode);
            return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}


#define ____FLEXE_HW_OP_____

STATIC int32
_sys_tmm_flexe_client_get_mcmac_tx_rx_en(uint8 lchip, sys_flexe_client_t** pp_client_node, uint32* tx_rx)
{
    uint8  rx_en  = 0;
    uint8  txqm_id = 0;
    uint16 mac_id = 0;
    uint32 val32  = 0;
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 step   = 0;
    uint32 factor = 0;
    uint32 lport  = 0;
    uint32 array32[2]  = {0};

    sys_flexe_client_t* client_node = *pp_client_node;
    McMacMacTxCfg_m            mac_cfg;
    uint8   dp_id      = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;
    NetRxWrEnCtl_m           aps_en_ctl;
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n ### %s @ %d\n", __FUNCTION__, __LINE__);

    *tx_rx &= SYS_FLEXE_USED_FLAG_U32_LOW_2;
    lport = CTC_MAP_GPORT_TO_LPORT(client_node->gport);
    if (SYS_FLEXE_UNUSED_FLAG_U16 == lport)
    {
        return CTC_E_NONE;
    }

    mac_id = client_node->mac_id;
    if (SYS_FLEXE_UNUSED_FLAG_U16 == mac_id)
    {
        return CTC_E_NONE;
    }

    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n ### %s @ %d, lport: %d\n", __FUNCTION__, __LINE__, lport);

    /*************** (I) memset 0 ****************/
    sal_memset(&mac_cfg, 0, sizeof(McMacMacTxCfg_m));

    port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
    if (!port_attr)
    {
        return CTC_E_NO_MEMORY;
    }

    dp_id = SYS_TMM_GET_DP_ID_FROM_CHANID(port_attr->chan_id);
    index = DRV_INS(dp_id, 0);
    cmd = DRV_IOR(NetRxWrEnCtl_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &aps_en_ctl);
    step = NetRxWrEnCtl_cfgWrEn1_f - NetRxWrEnCtl_cfgWrEn0_f;

    if (client_node->aps_role < 2)
    {
        factor = SYS_TMM_GET_MACID_PER_DP(port_attr->mac_id) / SYS_TMM_MAX_MAC_NUM_PER_TXQM;
        fld_id = NetRxWrEnCtl_cfgWrEn0_f + step*factor;
        DRV_IOR_FIELD(lchip, NetRxWrEnCtl_t, fld_id, array32, &aps_en_ctl);
        rx_en = (CTC_BMP_ISSET(array32, (port_attr->mac_id % SYS_TMM_MAX_MAC_NUM_PER_TXQM))?1:0);
    }
    else
    {
        factor = SYS_TMM_GET_MACID_PER_DP(port_attr->mac_id_aps) / SYS_TMM_MAX_MAC_NUM_PER_TXQM;
        fld_id = NetRxWrEnCtl_cfgWrEn0_f + step*factor;
        DRV_IOR_FIELD(lchip, NetRxWrEnCtl_t, fld_id, array32, &aps_en_ctl);
        rx_en = (CTC_BMP_ISSET(array32, (port_attr->mac_id_aps % SYS_TMM_MAX_MAC_NUM_PER_TXQM))?1:0);
    }

    txqm_id = SYS_TMM_GET_TXQM_BY_MACID(mac_id);
    /* #1, calc index */
    index = DRV_INS(txqm_id, 0);

    /* #2, read HW table: McMacMacTxCfg */
    tbl_id = McMacMacTxCfg_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mac_cfg));

        /* ##2.1. calc step */
    step = McMacMacTxCfg_cfgMcMacMacTx_1_cfgMcMacTxPktEn_f - McMacMacTxCfg_cfgMcMacMacTx_0_cfgMcMacTxPktEn_f;
    factor = SYS_TMM_GET_MACID_PER_TXQM(mac_id);/* 0..39 per txqm */

    /* ##2.2. modify field value */
    /* ###2.2.1. */
    fld_id = McMacMacTxCfg_cfgMcMacMacTx_0_cfgMcMacTxPktEn_f + step*factor;
    DRV_IOR_FIELD(lchip, McMacMacTxCfg_t, fld_id, &val32, &mac_cfg);

    (*tx_rx) |= (rx_en?0x1:0);
    (*tx_rx) |= (val32?0x2:0);

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_ignore_local_fault(uint8 lchip, sys_flexe_group_t* group_node, uint8 enable)
{
    uint8  txqm_id      = 0;
    uint8  link_stat    = 0;  /*1-up  0-down*/
    uint32 tbl_id       = 0;
    uint32 fld_id       = 0;
    uint32 cmd          = 0;
    uint32 index        = 0;
    uint32 step         = 0;
    uint32 factor       = 0;
    uint32 val32        = 0;
    uint32 write_st[SYS_MAC_MAX_STRUCT_WORD] = {0};

    sys_flexe_client_t* tmp_client_node = NULL;
    ctc_slistnode_t* node = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n ### %s @ %d, group_id: %d\n", __FUNCTION__, __LINE__, group_node->group_id);

    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
    {
        tmp_client_node = _ctc_container_of(node, sys_flexe_client_t, head);
        SYS_CONDITION_CONTINUE(!tmp_client_node);
        SYS_CONDITION_CONTINUE(group_node->group_id != tmp_client_node->group_id);
        SYS_CONDITION_CONTINUE(SYS_FLEXE_CLIENT_RESIZE != tmp_client_node->rx.op);
        SYS_CONDITION_CONTINUE(SYS_FLEXE_UNUSED_FLAG_U16 == tmp_client_node->mac_id);
        /* if client is already down, then do not need to ignore fault */
        sys_tmm_flexe_get_client_link_up(lchip, tmp_client_node->client_id, &link_stat);
        SYS_CONDITION_CONTINUE((!link_stat) && enable);

        txqm_id = SYS_TMM_GET_TXQM_BY_MACID(tmp_client_node->mac_id);

        /*************** (I) McMacMiiRxCfg start! ****************/
        /* #1, calc index */
        index = DRV_INS(txqm_id, 0);

        /* #2, read HW table: McMacMiiRxCfg */
        tbl_id = McMacMiiRxCfg_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));

        /* ##2.1. calc step */
        step = McMacMiiRxCfg_cfgMcMacMiiRx_1_cfgMcMacMiiRxFaultMaskLinkEn_f - McMacMiiRxCfg_cfgMcMacMiiRx_0_cfgMcMacMiiRxFaultMaskLinkEn_f;
        factor = SYS_TMM_GET_MACID_PER_TXQM(tmp_client_node->mac_id);
        /* ##2.2. modify field value */
        /* ###2.2.1. */
        fld_id = McMacMiiRxCfg_cfgMcMacMiiRx_0_cfgMcMacMiiRxFaultMaskLinkEn_f + step*factor;
        val32 = enable ? 0 : 1;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, write_st, txqm_id, 0);

        /* #3, write HW table: McMacMiiRxCfg*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
        /*************** (I) McMacMiiRxCfg end! ****************/

        /*************** (II) McMacMiiTxCfg start! ****************/
        /* #1, calc index */
        index = DRV_INS(txqm_id, 0);

        /* #2, read HW table: McMacMiiRxCfg */
        tbl_id = McMacMiiTxCfg_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));

        /* ##2.1. calc step */
        step = McMacMiiTxCfg_cfgMcMacMiiTx_1_cfgMcMacTxIgnoreLocalFault_f - McMacMiiTxCfg_cfgMcMacMiiTx_0_cfgMcMacTxIgnoreLocalFault_f;
        factor = SYS_TMM_GET_MACID_PER_TXQM(tmp_client_node->mac_id);
        /* ##2.2. modify field value */
        /* ###2.2.1. */
        fld_id = McMacMiiTxCfg_cfgMcMacMiiTx_0_cfgMcMacTxIgnoreLocalFault_f + step*factor;
        val32 = enable ? 1 : 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, write_st, txqm_id, 0);

        /* #3, write HW table: McMacMiiRxCfg*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
        /*************** (II) McMacMiiTxCfg end! ****************/
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_set_rx_spare(uint8 lchip, sys_flexe_group_t* group_node, uint8 enable)
{
    uint32          cmd   = 0;
    uint32          index = 0;
    uint32          step  = 0;
    uint32          tbl_id = 0;
    uint32          fld_id = 0;
    uint32          val32  = 0;
    RxCtlInst0_m    inst_ctl;

    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n[FlexE] %s @ %d, group_id %d  %s\n", __FUNCTION__, __LINE__, group_node->group_id, enable?"enable":"disable");
    FLEXE_DUMP("\n[FlexE] %s @ %d, group_id %d set rx spare %s\n", __FUNCTION__, __LINE__, group_node->group_id, enable?"enable":"disable");

    /*************** RxCtlInst0 start! ****************/
    /* #1, calc index */
    index = DRV_INS(group_node->flexe_shim_id, 0);

    step = RxCtlInst1_t - RxCtlInst0_t;
    tbl_id = RxCtlInst0_t + step*group_node->inst_list[0];

    /* #2, read HW table */
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &inst_ctl));

    /* ##2.2. modify field value */
    /* ###2.2.1. */
    fld_id = RxCtlInst0_spare_f;
    val32 = (enable ? 1 : 0);
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &inst_ctl, group_node->flexe_shim_id, 0);

    /* #3, write HW table*/
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &inst_ctl));
    /*************** RxCtlInst0 end! ****************/

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_clear_inst_ohlock(uint8 lchip, uint8 flexe_shim_id, uint8 inst_id)
{
    uint32 tbl_id           = 0;
    uint32 fld_id           = 0;
    uint32 cmd              = 0;
    uint32 index            = 0;
    uint32 step             = 0;
    uint32 factor           = 0;
    uint32 val32            = 0;

    RxLatchedIntInst0_m  cm;

    /* #1, calc index */
    index = DRV_INS(flexe_shim_id, 0);

    /* #2, clear */
    step = RxLatchedIntInst1_t - RxLatchedIntInst0_t;
    factor = inst_id;
    tbl_id = RxLatchedIntInst0_t + step*factor;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));

    val32 = 0x1;
    fld_id = RxLatchedIntInst0_ohLock_f;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &cm, flexe_shim_id, 0);
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_clear_inst_crcerr_cnt(uint8 lchip, uint8 flexe_shim_id, uint8 inst_id)
{
    uint32 tbl_id           = 0;
    uint32 fld_id           = 0;
    uint32 cmd              = 0;
    uint32 index            = 0;
    uint32 step             = 0;
    uint32 factor           = 0;
    uint32 val32            = 0;

    RxCrcErrCntInst0_m  cm;

    /* #1, calc index */
    index = DRV_INS(flexe_shim_id, 0);

    /* #2, clear */
    step = RxCrcErrCntInst1_t - RxCrcErrCntInst0_t;
    factor = inst_id;
    tbl_id = RxCrcErrCntInst0_t + step*factor;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));

    val32 = 0x1;
    fld_id = RxCrcErrCntInst0_val_f;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &cm, flexe_shim_id, 0);
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_client_mii_link_status(uint8 lchip, sys_flexe_client_t* client_node, uint8* p_is_up)
{
    uint32 mac_id           = 0;
    uint32 index            = 0;
    uint32 tbl_id           = 0;
    uint32 fld_id           = 0;
    uint32 cmd              = 0;
    uint32 step             = 0;
    uint32 factor           = 0;
    uint32 val32            = 0;

    mac_id = client_node->mac_id;
    if (SYS_FLEXE_UNUSED_FLAG_U16 == mac_id)
    {
        SYS_USW_VALID_PTR_WRITE(p_is_up, 0);
        return CTC_E_NONE;
    }

    /* #1, calc index */
    index = SYS_TMM_GET_TXQM_BY_MACID(mac_id);

    /* #2, read HW table: McMacMiiTxCfg */
    tbl_id = McMacMiiRxDebugStats_t;

    /* ##2.1. calc step */
    step = McMacMiiRxDebugStats_dbgMcMacMiiRx_1_dbgMiiRxLinkStatus_f - McMacMiiRxDebugStats_dbgMcMacMiiRx_0_dbgMiiRxLinkStatus_f;
    factor = TXQM_INNER_MAC_ID(mac_id);/* 0..39 per txqm */ 

    /* ##2.2. get field value */
    fld_id = McMacMiiRxDebugStats_dbgMcMacMiiRx_0_dbgMiiRxLinkStatus_f + step*factor;

    /* #3, read HW table */
    cmd = DRV_IOR(tbl_id, fld_id);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &val32));

    if (p_is_up)
    {
        *p_is_up = (uint8)val32;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_inst_pcs_link_status(uint8 lchip, uint8 flexe_shim_id, uint8 asic_inst, uint8* p_pcs_link)
{
    uint32 pcs_x8_x16_index = 0;
    uint32 is_pcs_x16       = 0;    
    uint32 index            = 0;
    uint32 tbl_id           = 0;
    uint32 fld_id           = 0;
    uint32 cmd              = 0;
    uint32 step             = 0;
    uint32 factor           = 0;
    uint32 val32            = 0;
    int32 ret               = 0;
    sys_datapath_serdes_info_t* p_serdes  = NULL;
    sys_datapath_lport_attr_t* port_attr = NULL;
    sys_flexe_phy_t*    phy_node = NULL;

    phy_node = _sys_tmm_flexe_phy_lookup_by_inst(lchip, flexe_shim_id, asic_inst);
    if (!phy_node)
    {
        SYS_USW_VALID_PTR_WRITE(p_pcs_link, 0);
        return CTC_E_NONE;
    }

    /* get p_serdes */
    ret = sys_usw_datapath_get_serdes_info(lchip, phy_node->logical_serdes_base, &p_serdes);
    if (0 != ret)
    {
        SYS_USW_VALID_PTR_WRITE(p_pcs_link, 0);
        return CTC_E_NONE;
    }
    if (SYS_USW_MAX_PORT_NUM_PER_CHIP <= p_serdes->lport)
    {
        SYS_USW_VALID_PTR_WRITE(p_pcs_link, 0);
        return CTC_E_NONE;
    }    
    /* get port_attr */
    ret = sys_usw_mac_get_port_capability(lchip, p_serdes->lport, &port_attr);    
    if (0 != ret)
    {
        SYS_USW_VALID_PTR_WRITE(p_pcs_link, 0);
        return CTC_E_NONE;
    }

    SYS_TMM_GET_PCS_X8_X16_BY_TXQM(port_attr->txqm_id, is_pcs_x16, pcs_x8_x16_index);

    index = DRV_INS(pcs_x8_x16_index, 0);
    factor = port_attr->pcs_idx % (is_pcs_x16?16:8);  /* 0..16(X16) or 0..8(X8) per txqm */
    tbl_id = McPcsX8LanesRxChanMon_t;
    step   = McPcsX8LanesRxChanMon_monRxStatusChan_1_monRxSyncStatus_f - McPcsX8LanesRxChanMon_monRxStatusChan_0_monRxSyncStatus_f;
    fld_id = McPcsX8LanesRxChanMon_monRxStatusChan_0_monRxSyncStatus_f + step * factor;
    cmd = DRV_IOR(tbl_id, fld_id);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &val32));

    SYS_USW_VALID_PTR_WRITE(p_pcs_link, val32);

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_inst_ohlock(uint8 lchip, uint8 flexe_shim_id, uint8 asic_inst, uint8* p_lock)
{
    uint32 index    = 0;
    uint32 cmd      = 0;
    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    uint32 val32    = 0;
    uint32 mask     = 0;
    uint8 lock      = 0;
    uint8 pcs_link  = 0;

    FlexeMgrMon_m mgr_mon;

    /* #1, calc index */
    index = DRV_INS(flexe_shim_id, 0);

    /* #2, read HW table */
    mask = asic_inst;
    tbl_id = FlexeMgrMon_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &mgr_mon);

    fld_id = FlexeMgrMon_monOverheadLock_f;
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &mgr_mon);
    val32 = (val32 >> mask) & 1;
    lock = (uint8)val32;

    if (lock)
    {
        _sys_tmm_flexe_get_inst_pcs_link_status(lchip, flexe_shim_id, asic_inst, &pcs_link);
        if (!pcs_link)
        {
            lock = 0;
        }
    }

    if (p_lock)
    {
        *p_lock = lock;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_inst_ohmflock(uint8 lchip, uint8 flexe_shim_id, uint8 asic_inst, uint8* p_lock)
{
    uint32 index    = 0;
    uint32 cmd      = 0;
    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    uint32 val32    = 0;
    uint32 mask     = 0;
    uint8 lock      = 0;
    uint8 pcs_link  = 0;

    FlexeMgrMon_m mgr_mon;

    /* #1, calc index */
    index = DRV_INS(flexe_shim_id, 0);

    /* #2, read HW table */
    mask = asic_inst;
    tbl_id = FlexeMgrMon_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &mgr_mon);

    fld_id = FlexeMgrMon_monOverheadMfLock_f;
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &mgr_mon);
    val32 = (val32 >> mask) & 1;
    lock = (uint8)val32;

    if (lock)
    {
        _sys_tmm_flexe_get_inst_pcs_link_status(lchip, flexe_shim_id, asic_inst, &pcs_link);
        if (!pcs_link)
        {
            lock = 0;
        }
    }

    if (p_lock)
    {
        *p_lock = lock;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_oh_get_banksel_config(uint8 lchip, uint8 flexe_shim_id, uint32 inst_mask, uint32 *p_bs)
{
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;

    FlexeMiscCfg_m flexe_misc;

    index = DRV_INS(flexe_shim_id, 0);

    tbl_id = FlexeMiscCfg_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &flexe_misc));

    fld_id = FlexeMiscCfg_txOhBankSelBmp_f;
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &flexe_misc);

    if (p_bs)
    {
        *p_bs = (val32 & inst_mask) ? 1 : 0;
    }

    FLEXE_DBG_PRINTF("\ninst_mask = 0x%x, val32 = 0x%x, read bs = 0x%x\n", inst_mask, val32, *p_bs);

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_oh_set_banksel_config(uint8 lchip, uint8 flexe_shim_id, uint32 inst_mask, uint32 bs)
{
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;
    FlexeMiscCfg_m flexe_misc;

    index = DRV_INS(flexe_shim_id, 0);

    tbl_id = FlexeMiscCfg_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &flexe_misc));

    fld_id = FlexeMiscCfg_txOhBankSelBmp_f;
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &flexe_misc);

    FLEXE_DBG_PRINTF("inst_mask = 0x%x, write bs = %d, read val32 = 0x%x, ", inst_mask, bs, val32);

    if (bs)
    {
        val32 |= inst_mask;
    }
    else
    {
        val32 &= ~inst_mask;
    }
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &flexe_misc, flexe_shim_id, 0);

    FLEXE_DBG_PRINTF("write val32 = 0x%x\n", val32);

    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &flexe_misc));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_ohram_clear_per_inst(uint8 lchip, uint8 flexe_shim_id, uint32 inst_id)
{
    uint32          cmd   = 0;
    uint32          entry = 0;
    uint32          index = 0;
    uint32          step  = 0;
    uint32          factor = 0;
    uint32          tbl_id = 0;
    uint32          fld_id = 0;
    uint32          val32  = 0;
    uint8           i = 0, k = 0;
    TxOhFrameRamInst0_m   ohram;

    FLEXE_DBG_PRINTF("clear oh ram inst %d\n", inst_id);

    step = TxOhFrameRamInst1_t - TxOhFrameRamInst0_t;
    for (i = 0; i < SYS_FLEXE_OH_FRAME_NUM; i++)
    {
        for (k = 0; k < SYS_FLEXE_OHRAM_BLKNUM; k++)
        {
            /* #1, calc index */
            entry = i * SYS_FLEXE_OHRAM_BLKNUM + k;
            index = DRV_INS(flexe_shim_id, entry);

            factor = inst_id;
            tbl_id = TxOhFrameRamInst0_t;
            tbl_id += step*factor;

            /* #2, read HW table */
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ohram));

            /* ##2.2. modify field value */
            /* ###2.2.1. */

            val32 = 0;
            fld_id = TxOhFrameRamInst0_ohFrame_f;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &ohram, flexe_shim_id, entry);

            /* #3, write HW table*/
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ohram));
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_ohram_clear(uint8 lchip, uint8 flexe_shim_id)
{
    uint8 i = 0;
    uint32 inst_id = 0;
    uint32 oh_bs = 0;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT);i++)
    {
        inst_id = i;
        CTC_ERROR_RETURN(_sys_tmm_flexe_oh_get_banksel_config(lchip, flexe_shim_id, (1<<inst_id), &oh_bs));
        CTC_ERROR_RETURN(_sys_tmm_flexe_oh_set_banksel_config(lchip, flexe_shim_id, (1<<inst_id), !oh_bs));
        CTC_ERROR_RETURN(_sys_tmm_flexe_ohram_clear_per_inst(lchip, flexe_shim_id, inst_id));
        CTC_ERROR_RETURN(_sys_tmm_flexe_oh_set_banksel_config(lchip, flexe_shim_id, (1<<inst_id), oh_bs));
        CTC_ERROR_RETURN(_sys_tmm_flexe_ohram_clear_per_inst(lchip, flexe_shim_id, inst_id));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_inst_hw_ow_oh(uint8 lchip,
                             uint8 flexe_shim_id,
                             uint8 inst_id,
                             uint8 ohmf_cnt,
                             uint8 type, /* sys_flexe_oh_field_type_t */
                             uint32 **val_cfg)
{
    uint32 val32     = 0;
    uint32 frame_id  = 0;
    uint32 blk_idx   = 0;
    uint32 fld_idx   = 0;
    uint32 cmd       = 0;
    uint32 entry     = 0;
    uint32 index     = 0;
    uint32 field     = 0;
    uint8  start_bit = 0;
    uint32 mask      = 0;
    //uint8  phy_speed = 0;
    const uint32 step = TxOhFrameRamInst1_t - TxOhFrameRamInst0_t;
    uint32 tbl_id     = TxOhFrameRamInst0_t + step*inst_id;
    TxOhFrameRamInst0_m  oh_ram;

    FLEXE_DBG_PRINTF("\n[FlexE] %s @ %d, inst_id %u, omf_cnt %u\n", __FUNCTION__, __LINE__, inst_id, ohmf_cnt);

    for (frame_id = 0; frame_id < ohmf_cnt; frame_id++)
    {
        for (blk_idx = 0; blk_idx < 5; blk_idx++)
        {
            entry = frame_id * SYS_FLEXE_OHRAM_BLKNUM + g_halfblk_fld[blk_idx].halfblk_id;
            index = DRV_INS(flexe_shim_id, entry);

            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &oh_ram));

            DRV_IOR_FIELD(lchip, tbl_id, TxOhFrameRamInst0_ohFrame_f, &val32, &oh_ram);

            FLEXE_DBG_PRINTF("[OHram curr value] frame_id = %d, entry = %d, val32 = 0x%x\n", frame_id, entry, val32);
            SYS_CONDITION_CONTINUE(((FLEXE_OH_FIELD_TYPE_GROUP_NUM == type) && (0 != blk_idx))      /* blk_idx: 0 */
                || ((FLEXE_OH_FIELD_TYPE_FLEXE_MAP == type) && (1 != blk_idx))   /* blk_idx: 1 */
                || ((FLEXE_OH_FIELD_TYPE_INST_NUM == type) && (1 != blk_idx))    /* blk_idx: 1 */
                || (((FLEXE_OH_FIELD_TYPE_CLIENT_CAL_A == type) || (FLEXE_OH_FIELD_TYPE_CLIENT_CAL_B == type)) && (2 > blk_idx))   /* blk_idx: 2, 3 */
                || ((FLEXE_OH_FIELD_TYPE_CR == type) && (3 != blk_idx))          /* blk_idx: 3 */
                || ((FLEXE_OH_FIELD_TYPE_CA == type) && (3 != blk_idx))          /* blk_idx: 3 */
                || ((FLEXE_OH_FIELD_TYPE_C_BIT == type) && (3 == blk_idx))       /* blk_idx: 0, 1, 2 */
                || ((FLEXE_OH_FIELD_TYPE_SC == type) && (4 != blk_idx))          /* blk_idx: 4 */
                );
            for(fld_idx = 0; fld_idx < g_halfblk_fld[blk_idx].field_num; fld_idx++)
            {
                field = g_halfblk_fld[blk_idx].field[fld_idx];
                SYS_CONDITION_CONTINUE(\
                       ((FLEXE_OH_FIELD_TYPE_GROUP_NUM == type) && (FLEXE_OH_FIELD_GRP_NUM != field))\
                    || ((FLEXE_OH_FIELD_TYPE_FLEXE_MAP == type) && (FLEXE_OH_FIELD_MAP != field))\
                    || ((FLEXE_OH_FIELD_TYPE_INST_NUM == type) && (FLEXE_OH_FIELD_INST_NUM != field))\
                    || (((FLEXE_OH_FIELD_TYPE_CLIENT_CAL_A == type) || (FLEXE_OH_FIELD_TYPE_CLIENT_CAL_B == type))\
                        && (FLEXE_OH_FIELD_CAL_A != field) && (FLEXE_OH_FIELD_CAL_B != field) && (FLEXE_OH_FIELD_CAL_B_15 != field))\
                    || ((FLEXE_OH_FIELD_TYPE_CR == type) && (FLEXE_OH_FIELD_CR != field))\
                    || ((FLEXE_OH_FIELD_TYPE_CA == type) && (FLEXE_OH_FIELD_CA != field))\
                    || ((FLEXE_OH_FIELD_TYPE_C_BIT == type) && (FLEXE_OH_FIELD_C_0 != field) && (FLEXE_OH_FIELD_C_1 != field) && (FLEXE_OH_FIELD_C_2 != field))\
                    || ((FLEXE_OH_FIELD_TYPE_CR_C == type) && (FLEXE_OH_FIELD_C_0 != field) && (FLEXE_OH_FIELD_C_1 != field) && (FLEXE_OH_FIELD_C_2 != field) && (FLEXE_OH_FIELD_CR != field))\
                    || ((FLEXE_OH_FIELD_TYPE_SC == type) && (FLEXE_OH_FIELD_SC != field))\
                    );
                start_bit = g_flexe_oh_field_info[field][FLEXE_OH_INFO_START_BIT];
                mask      = g_flexe_oh_field_info[field][FLEXE_OH_INFO_MASK];
                val32     = (val32 & mask) | ((val_cfg[field][frame_id] << start_bit) & (~mask));
                FLEXE_DBG_PRINTF("^^^^^^ type %u\tfield %u\tstart_bit %u\tmask 0x%08x\t   val_cfg 0x%x\tval32 0x%x\n", type, field, start_bit, mask, val_cfg[field][frame_id], val32);
            }

            FLEXE_DBG_PRINTF("[OHram updated value] frame_id = %d, entry = %d, val32 = 0x%x\n", frame_id, entry, val32);
            DRV_IOW_FIELD_NZ(lchip, tbl_id, TxOhFrameRamInst0_ohFrame_f, &val32, &oh_ram, flexe_shim_id, entry);
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &oh_ram));
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_send_ca(uint8 lchip, sys_flexe_group_t* group_node, uint32 ca_value)
{
    int8            si        = 0;
    uint32          inst_id   = 0;
    uint32          ca_bitmap = 0;
    uint32          cmd       = 0;
    uint32          index     = 0;
    SocFlexeCfg_m   soc_rst   = {{0}};

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n ### %s @ %d, group_id: %d\n", __FUNCTION__, __LINE__, group_node->group_id);

    cmd = DRV_IOR(SocFlexeCfg_t, DRV_ENTRY_FLAG);
    index = DRV_INS(group_node->flexe_shim_id, 0);
    DRV_IOCTL(lchip, index, cmd, &soc_rst);

    DRV_IOR_FIELD(lchip, SocFlexeCfg_t, SocFlexeCfg_cfgTxManualCaValue_f, &ca_bitmap, &soc_rst);

    /* from high to low, HW specified */
    for (si = group_node->inst_cnt-1; si >= 0; si--)
    {
        inst_id = group_node->inst_list[si];
        if (ca_value)
        {
            ca_bitmap |= (1 << inst_id);
        }
        else
        {
            ca_bitmap &= ~(1 << inst_id);
        }
    }

    DRV_IOW_FIELD_NZ(lchip, SocFlexeCfg_t, SocFlexeCfg_cfgTxManualCaValue_f, &ca_bitmap, &soc_rst, group_node->flexe_shim_id, 0);
    cmd = DRV_IOW(SocFlexeCfg_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &soc_rst); 

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_mac_flexe_en(uint8 lchip, uint8 txqm_id, uint8 enable)
{
    uint32 index  = 0;
    uint32 tbl_id = 0;
    uint32 cmd    = 0;
    uint32 fld_id = 0;
    uint32 val32  = 0;
    McMacFlexEEnCfg_m     macflexe_en;

    /*************** (I) McMacFlexEEnCfg start! ****************/
    /* #1, calc index */
    index = DRV_INS(txqm_id, 0);

    /* #2, read HW table */
    tbl_id = McMacFlexEEnCfg_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macflexe_en));

    /* ###2.2.1. */
    fld_id = McMacFlexEEnCfg_cfgMcMacFlexEEn_f;
    val32 = enable ? 1 : 0;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &macflexe_en, txqm_id, 0);

    /* #3, write HW table*/
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macflexe_en));
    /*************** (I) McMacFlexEEnCfg end! ****************/

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_mac_flexe_en(uint8 lchip, uint8 txqm_id, uint8 *p_enable)
{
    uint32 index  = 0;
    uint32 tbl_id = 0;
    uint32 cmd    = 0;
    uint32 fld_id = 0;
    uint32 val32  = 0;
    McMacFlexEEnCfg_m     macflexe_en;

    /*************** (I) McMacFlexEEnCfg start! ****************/
    /* #1, calc index */
    index = DRV_INS(txqm_id, 0);

    /* #2, read HW table */
    tbl_id = McMacFlexEEnCfg_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macflexe_en));

    /* ###2.2.1. */
    fld_id = McMacFlexEEnCfg_cfgMcMacFlexEEn_f;
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &macflexe_en);
    /*************** (I) McMacFlexEEnCfg end! ****************/

    if (p_enable)
    {
        *p_enable = val32;
    }

    return CTC_E_NONE;
}

int32
_sys_tmm_flexe_get_hw_enable(uint8 lchip, uint8 txqm_id, uint8 *p_en)
{
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_mac_flexe_en(lchip, txqm_id, p_en));
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_cross_get_banksel_config(uint8 lchip, uint8 flexe_shim_id, uint8 dir, uint32 *p_bs)
{
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;

    TxMainCtrl_m tx_bs;
    RxMainCtrl_m rx_bs;

    index = DRV_INS(flexe_shim_id, 0);

    if (SYS_FLEXE_DIR_TX == dir)
    {
        tbl_id = TxMainCtrl_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_bs));

        fld_id = TxMainCtrl_cfgTxBankSel_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &tx_bs);
    }
    else if (SYS_FLEXE_DIR_RX == dir)
    {
        tbl_id = RxMainCtrl_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_bs));

        fld_id = RxMainCtrl_cfgRxBankSel_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &rx_bs);
    }

    if (p_bs)
    {
        *p_bs = val32;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_cross_set_banksel_config(uint8 lchip, uint8 flexe_shim_id, uint8 dir, uint32 cross_bs)
{
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;

    TxMainCtrl_m tx_bs;
    RxMainCtrl_m rx_bs;

    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n[FlexE] %s @ %d, flexe_shim_id %d dir %s cross banksel %d\n", __FUNCTION__, __LINE__, flexe_shim_id, dir?"TX":"RX", cross_bs);

    index = DRV_INS(flexe_shim_id, 0);

    if (SYS_FLEXE_DIR_TX == dir)
    {
        tbl_id = TxMainCtrl_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_bs));

        fld_id = TxMainCtrl_cfgTxBankSel_f;
        val32 = cross_bs ? 1 : 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &tx_bs, flexe_shim_id, 0);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_bs));
    }
    else if (SYS_FLEXE_DIR_RX == dir)
    {
        tbl_id = RxMainCtrl_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_bs));

        fld_id = RxMainCtrl_cfgRxBankSel_f;
        val32 = cross_bs ? 1 : 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &rx_bs, flexe_shim_id, 0);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_bs));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_fifo_read_cfg(uint8 lchip, sys_flexe_client_t* client_node, uint8 enable)
{
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 step   = 0;
    uint32 factor = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;
    uint32 speed  = 0;
    McOutputFifoReadThrd0To3_m fifo_thrd;
    uint32 McOutputFifoReadThrd[] =
    {
        19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, \
        35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, \
        51, 52, 53, 54, 55, 56, 57, 58, 58, 58, 58, 58, 58, 58, 58, 58, \
        58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, \
        58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58
    };

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n[FlexE] %s @ %d, client id %d\n", __FUNCTION__, __LINE__, client_node->client_id);
    FLEXE_DBG_PRINTF("{ %s @ %d } client id %d flexe_shim_id %d table step = %d, factor = %d\n", __FUNCTION__, __LINE__, client_node->client_id, client_node->flexe_shim_id, step, factor);

    /* calc current speed */
    _sys_tmm_flexe_get_client_speed_val(lchip, client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_INACTIVE_FLAG, &speed);

    index = DRV_INS(client_node->flexe_shim_id, 0);

    tbl_id = McOutputFifoReadThrd0To3_t;
    step = McOutputFifoReadThrd4To7_t - McOutputFifoReadThrd0To3_t;
    factor = client_node->tx_xc_chid / 4;
    tbl_id += step*factor;

    step = McOutputFifoReadThrd0To3_thrd1_f - McOutputFifoReadThrd0To3_thrd0_f;
    factor = client_node->tx_xc_chid % 4;
    fld_id = McOutputFifoReadThrd0To3_thrd0_f + step*factor;

    FLEXE_DBG_PRINTF("{ %s @ %d } client id %d flexe_shim_id %d field step = %d, factor = %d\n", __FUNCTION__, __LINE__, client_node->client_id, client_node->flexe_shim_id, step, factor);

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &fifo_thrd));
    val32 = 0;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &fifo_thrd, client_node->flexe_shim_id, 0);
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &fifo_thrd));
    if (enable)
    {
        val32 = speed ? McOutputFifoReadThrd[speed/5 - 1] : 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &fifo_thrd, client_node->flexe_shim_id, 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &fifo_thrd));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_rate_comp(uint8 lchip, sys_flexe_client_t* client_node, sys_flexe_client_flow_t flow_type, uint8 enable)
{
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 step   = 0;
    uint32 factor = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;
    uint32 val32_2 = 0;
    uint32 speed   = 0;
    RateCompBReadThrd0To3_m rate_comp;
    uint32 RateCompBReadThrd[] =
    {
         6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, \
        16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \
        16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \
        16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \
        16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
    };

    uint32 RateCompACReadThrd[] = 
    {
        32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, \
        32, 32, 32, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, \
        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, \
        24, 24, 24, 24, 24, 24, 24,  4,  4,  4,  4,  4,  4,  4,  4,  4, \
         4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4
    };

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n[FlexE] %s @ %d, client id %d flow_type %d\n", __FUNCTION__, __LINE__, client_node->client_id, flow_type);

    index = DRV_INS(client_node->flexe_shim_id, 0);

    /* calc current speed */
    _sys_tmm_flexe_get_client_speed_val(lchip, client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_INACTIVE_FLAG, &speed);

    switch (flow_type)
    {
    case SYS_FLEXE_FLOW_TYPE_A:
        val32_2 = speed ? RateCompACReadThrd[speed/5-1] : 0;
        tbl_id = RateCompAReadThrd0To3_t;
        break;
    case SYS_FLEXE_FLOW_TYPE_B:
        val32_2 = speed ? RateCompBReadThrd[speed/5-1] : 0;
        tbl_id = RateCompBReadThrd0To3_t;
        break;
    case SYS_FLEXE_FLOW_TYPE_C:
        val32_2 = speed ? RateCompACReadThrd[speed/5-1] : 0;
        tbl_id = RateCompCReadThrd0To3_t;
        break;
    default:
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] client %d Flow Type is unkown! \n", client_node->flow_type);
        return CTC_E_NOT_SUPPORT;
    }

    step = RateCompBReadThrd4To7_t - RateCompBReadThrd0To3_t;
    if (SYS_FLEXE_FLOW_TYPE_B == flow_type)
    {
        factor = client_node->tx_xc_chid / 4;
    }
    else
    {
        factor = client_node->rx_xc_chid / 4;
    }
    tbl_id += step*factor;

    step = RateCompBReadThrd0To3_thrd1_f - RateCompBReadThrd0To3_thrd0_f;
    if (SYS_FLEXE_FLOW_TYPE_B == flow_type)
    {
        factor = client_node->tx_xc_chid % 4;
    }
    else
    {
        factor = client_node->rx_xc_chid % 4;
    }
    fld_id = RateCompBReadThrd0To3_thrd0_f + step*factor;

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rate_comp));
    val32 = 0;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &rate_comp, client_node->flexe_shim_id, 0);
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rate_comp));
    if (enable)
    {
        val32 = val32_2;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &rate_comp, client_node->flexe_shim_id, 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rate_comp));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_rate_comp_remove_idle_thrd(uint8 lchip, sys_flexe_client_t* client_node, sys_flexe_client_flow_t flow_type, uint8 enable)
{
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 step   = 0;
    uint32 factor = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;
    uint32 speed  = 0;
    RateCompARemoveIdleThrd0To3_m thrd;
    uint32 RateCompACRemoveIdleThrd[] = 
    {
        48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, \
        48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, \
        48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, \
        48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, \
        48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48
    };

    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n[FlexE] %s @ %d, client id %d\n", __FUNCTION__, __LINE__, client_node->client_id);

    index = DRV_INS(client_node->flexe_shim_id, 0);

    switch (flow_type)
    {
    case SYS_FLEXE_FLOW_TYPE_A:
        tbl_id = RateCompARemoveIdleThrd0To3_t;
        break;
    case SYS_FLEXE_FLOW_TYPE_C:
        tbl_id = RateCompCRemoveIdleThrd0To3_t;
        break;
    default:
    case SYS_FLEXE_FLOW_TYPE_B:
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] Invalid config for client %d! \n", client_node->client_id);
        return CTC_E_INVALID_PARAM;
    }

    _sys_tmm_flexe_get_client_speed_val(lchip, client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_ACTIVE_FLAG, &speed);

    step = RateCompARemoveIdleThrd4To7_t - RateCompARemoveIdleThrd0To3_t;
    factor = client_node->rx_xc_chid / 4;
    tbl_id += step*factor;

    step = RateCompARemoveIdleThrd0To3_thrd1_f - RateCompARemoveIdleThrd0To3_thrd0_f;
    factor = client_node->rx_xc_chid % 4;
    fld_id = RateCompARemoveIdleThrd0To3_thrd0_f + step*factor;

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &thrd));
    val32 = 0;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &thrd, client_node->flexe_shim_id, 0);
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &thrd));

    if (enable)
    {
        val32 = speed ? RateCompACRemoveIdleThrd[speed/5 - 1] : 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &thrd, client_node->flexe_shim_id, 0);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &thrd));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_rate_comp_insert_idle_thrd(uint8 lchip, sys_flexe_client_t* client_node, sys_flexe_client_flow_t flow_type, uint8 enable)
{
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 step   = 0;
    uint32 factor = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;
    uint32 speed  = 0;
    RateCompAInsertIdleThrd0To3_m thrd;
    uint32 RateCompACInsertIdleThrd[] = 
    {
        25, 25, 25, 25, 25, 25, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, \
        18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, \
        18, 18, 18, 18,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4, \
         4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  2,  2,  2,  2, \
         2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2
    };

    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n[FlexE] %s @ %d, client id %d\n", __FUNCTION__, __LINE__, client_node->client_id);

    index = DRV_INS(client_node->flexe_shim_id, 0);

    switch (flow_type)
    {
    case SYS_FLEXE_FLOW_TYPE_A:
        tbl_id = RateCompAInsertIdleThrd0To3_t;
        break;
    case SYS_FLEXE_FLOW_TYPE_C:
        tbl_id = RateCompCInsertIdleThrd0To3_t;
        break;
    default:
    case SYS_FLEXE_FLOW_TYPE_B:
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] Invalid config for client %d! \n", client_node->client_id);
        return CTC_E_INVALID_PARAM;
    }

    _sys_tmm_flexe_get_client_speed_val(lchip, client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_ACTIVE_FLAG, &speed);

    step = RateCompAInsertIdleThrd4To7_t - RateCompAInsertIdleThrd0To3_t;
    factor = client_node->rx_xc_chid / 4;
    tbl_id += step*factor;

    step = RateCompAInsertIdleThrd0To3_thrd1_f - RateCompAInsertIdleThrd0To3_thrd0_f;
    factor = client_node->rx_xc_chid % 4;
    fld_id = RateCompAInsertIdleThrd0To3_thrd0_f + step*factor;

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &thrd));
    val32 = 0;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &thrd, client_node->flexe_shim_id, 0);
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &thrd));
    if (enable)
    {
        val32 = speed ? RateCompACInsertIdleThrd[speed/5 - 1] : 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &thrd, client_node->flexe_shim_id, 0);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &thrd));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_fifo_full_thrd(uint8 lchip, sys_flexe_client_t* client_node, uint8 enable)
{
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 step   = 0;
    uint32 factor = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;
    uint32 speed  = 0;
    McOutputFifoFullThrd0To3_m thrd;
    uint32 McOutputFifoFullThrd[] = 
    {
        19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  \
        35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  \
        51,  52,  53,  54,  55,  56,  57,  58,  58,  58,  58,  58,  58,  58,  58,  58,  \
        58,  58,  58,  58,  58,  58,  58,  58,  58,  58,  58,  100, 100, 100, 100, 100, \
        100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100
    };

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n[FlexE] %s @ %d, client id %d\n", __FUNCTION__, __LINE__, client_node->client_id);

    /* calc current speed */
    _sys_tmm_flexe_get_client_speed_val(lchip, client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_INACTIVE_FLAG, &speed);

    index = DRV_INS(client_node->flexe_shim_id, 0);

    tbl_id = McOutputFifoFullThrd0To3_t;
    step = McOutputFifoFullThrd4To7_t - McOutputFifoFullThrd0To3_t;
    factor = client_node->tx_xc_chid / 4;
    tbl_id += step*factor;

    step = McOutputFifoFullThrd0To3_thrd1_f - McOutputFifoFullThrd0To3_thrd0_f;
    factor = client_node->tx_xc_chid % 4;
    fld_id = McOutputFifoFullThrd0To3_thrd0_f + step*factor;

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &thrd));
    val32 = 0;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &thrd, client_node->flexe_shim_id, 0);
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &thrd));
    if (enable)
    {
        val32 = speed ? McOutputFifoFullThrd[speed/5 - 1] : 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &thrd, client_node->flexe_shim_id, 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &thrd));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_cross_map_config(uint8 lchip, sys_flexe_client_t* client_node, sys_flexe_dir_t dir, uint8 enable)
{
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0; 
    uint32 val32  = 0;

    FlexeTxChanMap_m tx_chanmap;
    FlexeRxChanMap_m rx_chanmap;
    McMacTxPortMap_m port_map;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n[FlexE] %s @ %d, client id %d dir %s\n", __FUNCTION__, __LINE__, client_node->client_id, dir?"TX":"RX");

    if(SYS_FLEXE_DIR_TX == dir)
    {
        /********************* FlexeTxChanMap start! ***********************/
        /* #1, calc index */
        index = DRV_INS(client_node->flexe_shim_id, client_node->tx_xc_chid);

        /* #2.1, read HW table */
        tbl_id = FlexeTxChanMap_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_chanmap));

        /* ##2.3. modify field value */
        fld_id = FlexeTxChanMap_cfgMcMacTxChan_f;
        val32 = enable ? SYS_TMM_GET_MACID_PER_TXQM(client_node->mac_id) : 0x3f;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &tx_chanmap, client_node->flexe_shim_id, client_node->tx_xc_chid);

        fld_id = FlexeTxChanMap_cfgMcMacTxSel_f;
        val32 = enable ? (client_node->mac_id / SYS_TMM_MAX_MAC_NUM_PER_TXQM % 2) : 0; /* CS0 or CS1 select */
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &tx_chanmap, client_node->flexe_shim_id, client_node->tx_xc_chid);

       /* #3, write HW table*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_chanmap));
        /********************* FlexeTxChanMap end! ***********************/
        /*************** (V) McMacTxPortMap start! ****************/
        /* #1, calc index */
        index = DRV_INS((client_node->mac_id / SYS_TMM_MAX_MAC_NUM_PER_TXQM), \
            SYS_TMM_GET_MACID_PER_TXQM(client_node->mac_id));

        /* #2, read HW table: McMacTxPortMap */
        tbl_id = McMacTxPortMap_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &port_map));

        /* ##2.1. calc step */

        /* ##2.2. modify field value */
        /* ###2.2.1. */
        fld_id = McMacTxPortMap_portMap_f;
        val32 = enable ? client_node->tx_xc_chid : 0x3f;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &port_map, \
            (client_node->mac_id / SYS_TMM_MAX_MAC_NUM_PER_TXQM), \
            SYS_TMM_GET_MACID_PER_TXQM(client_node->mac_id));

        /* #3, write HW table: McMacTxPortMap*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &port_map));
        /*************** (V) McMacTxPortMap end! ****************/
    }
    else
    {
        /********************* FlexeRxChanMap start! ***********************/
        /* #1, calc index */
        index = DRV_INS(client_node->flexe_shim_id, client_node->tx_xc_chid);

        /* #2.1, read HW table */
        tbl_id = FlexeRxChanMap_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_chanmap));

        /* ##2.3. modify field value */
        fld_id = FlexeRxChanMap_cfgMcMacRxChan_f;
        val32 = enable ? SYS_TMM_GET_MACID_PER_TXQM(client_node->mac_id) : 0x3f;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &rx_chanmap, client_node->flexe_shim_id, client_node->tx_xc_chid);

        fld_id = FlexeRxChanMap_cfgMcMacRxSel_f;
        val32 = enable ? (client_node->mac_id / SYS_TMM_MAX_MAC_NUM_PER_TXQM % 2) : 0; /* CS0 or CS1 select */
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &rx_chanmap, client_node->flexe_shim_id, client_node->tx_xc_chid);

       /* #3, write HW table*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_chanmap));
        /********************* FlexeRxChanMap end! ***********************/
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_cal_config(uint8 lchip, uint8 flexe_shim_id, sys_flexe_client_calcfg_t* flexe_client_cal)
{
    uint32 tbl_id  = 0;
    uint32 fld_id  = 0;
    uint32 step_f  = 0;
    uint32 factor_f = 0;
    uint32 cmd     = 0;
    uint32 index   = 0;
    uint8  cycle   = 0;
    uint32 entry   = 0;
    uint32 val32   = 0;
    TxSelSchEntryRam_m   txsel_sch;
    TxSelOutputMapRam_m  txoutput;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n[FlexE] %s @ %d\n", __FUNCTION__, __LINE__);

    tbl_id = TxSelSchEntryRam_t;
    for (cycle = 0; cycle < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); cycle++)
    {
        entry = cycle / 2;
        index = DRV_INS(flexe_shim_id, entry);

        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &txsel_sch));

        step_f = TxSelSchEntryRam_chIdOdd_f - TxSelSchEntryRam_chIdEven_f;
        factor_f = cycle%2;
        fld_id = TxSelSchEntryRam_chIdEven_f + step_f*factor_f;

        val32 = flexe_client_cal[cycle].rx_xc_chid;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &txsel_sch, flexe_shim_id, entry);

        FLEXE_DBG_PRINTF("cycle: %d, flow id = %d\n", cycle, val32);
        step_f = TxSelSchEntryRam_flowIdOdd_f - TxSelSchEntryRam_flowIdEven_f;
        factor_f = cycle%2;
        fld_id = TxSelSchEntryRam_flowIdEven_f + step_f*factor_f;

        val32 = flexe_client_cal[cycle].flow_type;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &txsel_sch, flexe_shim_id, entry);

        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &txsel_sch));
    }

    tbl_id = TxSelOutputMapRam_t;
    for (cycle = 0; cycle < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); cycle++)
    {
        entry = cycle / 2;
        index = DRV_INS(flexe_shim_id, entry);

        step_f = TxSelOutputMapRam_slotChIdOdd_f - TxSelOutputMapRam_slotChIdEven_f;
        factor_f = cycle%2;
        fld_id = TxSelOutputMapRam_slotChIdEven_f + step_f*factor_f;

        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &txoutput));

        val32 = flexe_client_cal[cycle].xc_chid;

        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &txoutput, flexe_shim_id, entry);

        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &txoutput));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_macrx_cal_config(uint8 lchip, uint8 dp_id, sys_flexe_client_calcfg_t* flexe_client_cal)
{
    uint8 i = 0, j = 0;
    uint8 txqm  = 0;
    uint8 txqm_base = 0;

    uint32 tbl_id  = 0;
    uint32 fld_id  = 0;
    uint32 cmd     = 0;
    uint32 index   = 0;
    uint8  cycle   = 0;
    uint32 val32   = 0;
    uint32 walkend = 0;
    uint32 is_back_cal  = 0;
    uint16 entry[2][SYS_FLEXE_MAX_CYCLE] = {{0}};
    uint32 cs_entry_cnt[2] = {0};

    McMacRxCal_m   macrx_cal;
    McMacCalCtrl_m cal_ctrl;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n[FlexE] %s @ %d\n", __FUNCTION__, __LINE__);

    for (cycle = 0; cycle < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); cycle++)
    {
        SYS_CONDITION_CONTINUE(SYS_FLEXE_UNUSED_FLAG_U8 == flexe_client_cal[cycle].xc_chid);
        SYS_CONDITION_CONTINUE(SYS_FLEXE_UNUSED_FLAG_U16 == flexe_client_cal[cycle].mac_id);
        FLEXE_DBG_PRINTF("cycle %d , xc_chid = %d, mac_id = %d\n", cycle, flexe_client_cal[cycle].xc_chid, flexe_client_cal[cycle].mac_id);

        if (flexe_client_cal[cycle].mac_id >= 120 + dp_id*SYS_TMM_MAX_MAC_NUM_PER_DP)
        {
            entry[1][cs_entry_cnt[1]++] = flexe_client_cal[cycle].mac_id % SYS_TMM_MAX_MAC_NUM_PER_TXQM;
        }
        else
        {
            entry[0][cs_entry_cnt[0]++] = flexe_client_cal[cycle].mac_id % SYS_TMM_MAX_MAC_NUM_PER_TXQM;
        }
    }

    FLEXE_DBG_PRINTF("CS0: cs_entry_cnt = %d\n", cs_entry_cnt[0]);
    FLEXE_DBG_PRINTF("CS1: cs_entry_cnt = %d\n", cs_entry_cnt[1]);

    txqm_base = 2;
    txqm_base += ((0 == dp_id) ? 0 : 4);

    for (i = 0; i < 2; i++)
    {
        SYS_CONDITION_CONTINUE(!cs_entry_cnt[i]);
        txqm = txqm_base + i;
        index = DRV_INS(txqm, 0);
        cmd = DRV_IOR(McMacCalCtrl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cal_ctrl));

        val32 = GetMcMacCalCtrl(V, cfgMcMacRxReady_f, &cal_ctrl);
        is_back_cal = GetMcMacCalCtrl(V, cfgRxCalEntrySel_f, &cal_ctrl);
        if(!val32)
            is_back_cal = 0;
        else
            is_back_cal = is_back_cal ? 0 : 1;

        /* WalkerEnd */
        walkend = cs_entry_cnt[i] - 1;
        fld_id = (is_back_cal ? McMacCalCtrl_cfgRxWalkerEndBak_f : McMacCalCtrl_cfgRxWalkerEnd_f);
        DRV_IOW_FIELD_NZ(lchip, McMacCalCtrl_t, fld_id, &walkend, &cal_ctrl, txqm, 0);
        cmd = DRV_IOW(McMacCalCtrl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cal_ctrl));

        /***************** Mac Rx Cal *********************/
        /* calEntry */
        tbl_id = (is_back_cal ? McMacRxCalBak_t : McMacRxCal_t);
        fld_id = (is_back_cal ? McMacRxCalBak_calEntry_f : McMacRxCal_calEntry_f);
        /* re-init 80-cycle cal entry */
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); j++)
        {
            index = DRV_INS(txqm, j);
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macrx_cal));
            val32 = 0x3f;
            DRV_IOW_FIELD_NZ(lchip,tbl_id, fld_id, &val32, &macrx_cal, txqm, j);

            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macrx_cal));
        }
        /* update calculated cal entry */
        for (j = 0; j < cs_entry_cnt[i]; j++)
        {
            index = DRV_INS(txqm, j);
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macrx_cal));
            val32 = entry[i][j];
            DRV_IOW_FIELD_NZ(lchip,tbl_id, fld_id, &val32, &macrx_cal, txqm, j);

            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macrx_cal));
        }

        /* entry sel */
        index = DRV_INS(txqm, 0);
        cmd = DRV_IOR(McMacCalCtrl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cal_ctrl));
        val32 = is_back_cal;
        DRV_IOW_FIELD_NZ(lchip, McMacCalCtrl_t, McMacCalCtrl_cfgRxCalEntrySel_f, &val32, &cal_ctrl, txqm, 0);
        cmd = DRV_IOW(McMacCalCtrl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cal_ctrl));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_cross_cal_config(uint8 lchip, uint8 flexe_shim_id, sys_flexe_client_calcfg_t* flexe_client_cal)
{
    uint32 cross_bs = 0;
    CTC_ERROR_RETURN(_sys_tmm_flexe_client_cal_config(lchip, flexe_shim_id, flexe_client_cal));
    CTC_ERROR_RETURN(_sys_tmm_flexe_cross_get_banksel_config(lchip, flexe_shim_id, SYS_FLEXE_DIR_TX, &cross_bs));
    CTC_ERROR_RETURN(_sys_tmm_flexe_cross_set_banksel_config(lchip, flexe_shim_id, SYS_FLEXE_DIR_TX, !cross_bs));
    FLEXE_DBG_PRINTF("4 ");
    CTC_ERROR_RETURN(_sys_tmm_flexe_client_cal_config(lchip, flexe_shim_id, flexe_client_cal));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_inst_en(uint8 lchip, uint32 flexe_shim_id, uint32 inst_id, uint8 dir, uint8 enable)
{
    uint32          cmd   = 0;
    uint32          value = 0;
    uint32          index = 0;
    uint32          step  = 0;
    uint32          tbl_id = 0;

    TxCtlInst0_m    inst_tx_rst;
    RxCtlInst0_m    inst_rx_rst; 

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s() @ %d, flexe_shim_id %d, instance %d, dir %s, enable %d\n", __FUNCTION__, __LINE__, flexe_shim_id, inst_id, dir?"TX":"RX", enable);

    sal_memset(&inst_tx_rst, 0, sizeof(TxCtlInst0_m));
    sal_memset(&inst_rx_rst, 0, sizeof(RxCtlInst0_m));

    value = enable ? 0 : 1;

    if (SYS_FLEXE_DIR_TX == dir)
    {
        step = TxCtlInst1_t - TxCtlInst0_t;
        tbl_id = TxCtlInst0_t + step*inst_id;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        index = DRV_INS(flexe_shim_id, 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &inst_tx_rst));
        DRV_IOW_FIELD_NZ(lchip, tbl_id, TxCtlInst0_swReset_f, &value, &inst_tx_rst, flexe_shim_id, 0);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &inst_tx_rst));
    }
    else
    {
        step = RxCtlInst1_t - RxCtlInst0_t;
        tbl_id = RxCtlInst0_t + step*inst_id;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        index = DRV_INS(flexe_shim_id, 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &inst_rx_rst));
        DRV_IOW_FIELD_NZ(lchip, tbl_id, RxCtlInst0_swReset_f, &value, &inst_rx_rst, flexe_shim_id, 0);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &inst_rx_rst));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_cross_en(uint8 lchip, uint32 flexe_shim_id, uint8 dir, uint8 enable)
{
    uint32          cmd   = 0;
    uint32          value = 0;
    uint32          index = 0;

    TxMainCtrl_m    xc_tx_rst;
    RxMainCtrl_m    xc_rx_rst; 

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s() @ %d, flexe_shim_id %d, dir %s, cross enable %d\n", __FUNCTION__, __LINE__, flexe_shim_id, dir?"TX":"RX", enable);

    sal_memset(&xc_tx_rst, 0, sizeof(TxMainCtrl_m));
    sal_memset(&xc_rx_rst, 0, sizeof(RxMainCtrl_m));

    value = enable ? 0 : 1;

    if (SYS_FLEXE_DIR_TX == dir)
    {
        cmd = DRV_IOR(TxMainCtrl_t, DRV_ENTRY_FLAG);
        index = DRV_INS(flexe_shim_id, 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &xc_tx_rst));
        DRV_IOW_FIELD_NZ(lchip, TxMainCtrl_t, TxMainCtrl_cfgTxReset_f, &value, &xc_tx_rst, flexe_shim_id, 0);
        cmd = DRV_IOW(TxMainCtrl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &xc_tx_rst));
    }
    else
    {
        cmd = DRV_IOR(RxMainCtrl_t, DRV_ENTRY_FLAG);
        index = DRV_INS(flexe_shim_id, 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &xc_rx_rst));
        DRV_IOW_FIELD_NZ(lchip, RxMainCtrl_t, RxMainCtrl_cfgRxReset_f, &value, &xc_rx_rst, flexe_shim_id, 0);
        cmd = DRV_IOW(RxMainCtrl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &xc_rx_rst));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_soc_en(uint8 lchip, uint32 flexe_shim_id, uint8 enable)
{
    uint32          cmd   = 0;
    uint32          value = 0;
    uint32          index = 0;

    SocFlexeCfg_m   soc_cfg;

    sal_memset(&soc_cfg, 0, sizeof(SocFlexeCfg_m));

    cmd = DRV_IOR(SocFlexeCfg_t, DRV_ENTRY_FLAG);
    index = DRV_INS(flexe_shim_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &soc_cfg));
    value = enable ? 0 : 1;
    DRV_IOW_FIELD_NZ(lchip, SocFlexeCfg_t, SocFlexeCfg_socReset_f, &value, &soc_cfg, flexe_shim_id, 0);

    value = 0xff;
    DRV_IOW_FIELD_NZ(lchip, SocFlexeCfg_t, SocFlexeCfg_cfgAutoTxCaDisable_f, &value, &soc_cfg, flexe_shim_id, 0);

    value = enable ? 1 : 0;
    DRV_IOW_FIELD_NZ(lchip, SocFlexeCfg_t, SocFlexeCfg_cfgPhyDownProtect_f, &value, &soc_cfg, flexe_shim_id, 0);

    cmd = DRV_IOW(SocFlexeCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &soc_cfg));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_cross_init(uint8 lchip, uint8 flexe_shim_id)
{
    uint32 tbl_id  = 0;
    uint32 fld_id  = 0;
    uint32 step_f  = 0;
    uint32 factor_f = 0;
    uint32 cmd     = 0;
    uint32 index   = 0;
    uint32 entry   = 0;
    uint32 val32   = 0;
    uint32 id      = 0;
    uint32 cycle   = 0;
    uint32 cross_txbs  = 0;
    uint32 cross_rxbs  = 0;
    TxSelSchEntryRam_m   txsel_sch;
    TxSelOutputMapRam_m  txoutput;
    RxSelOutputMapRam_m  rxoutput;

    /********************TxSelSchEntryRam_t********************/
    tbl_id = TxSelSchEntryRam_t;
    for (cycle = 0; cycle < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); cycle++)
    {
        entry = cycle / 2;
        index = DRV_INS(flexe_shim_id, entry);

        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &txsel_sch));

        val32 = SYS_FLEXE_UNUSED_FLAG_U8;
        step_f = TxSelSchEntryRam_chIdOdd_f - TxSelSchEntryRam_chIdEven_f;
        factor_f = cycle%2;
        fld_id = TxSelSchEntryRam_chIdEven_f + step_f*factor_f;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &txsel_sch, flexe_shim_id, entry);

        val32 = SYS_FLEXE_FLOW_MAX;
        fld_id = TxSelSchEntryRam_flowIdEven_f;
        step_f = TxSelSchEntryRam_flowIdOdd_f - TxSelSchEntryRam_flowIdEven_f;
        factor_f = cycle%2;
        fld_id = TxSelSchEntryRam_flowIdEven_f + step_f*factor_f;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &txsel_sch, flexe_shim_id, entry);

        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &txsel_sch));
    }
    /********************TxSelSchEntryRam_t********************/

    /********************TxSelOutputMapRam_t********************/
    tbl_id = TxSelOutputMapRam_t;
    for (cycle = 0; cycle < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); cycle++)
    {
        entry = cycle / 2;
        index = DRV_INS(flexe_shim_id, entry);
        step_f = TxSelOutputMapRam_slotChIdOdd_f - TxSelOutputMapRam_slotChIdEven_f;
        factor_f = cycle%2;
        fld_id = TxSelOutputMapRam_slotChIdEven_f + step_f*factor_f;

        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &txoutput));

        val32 = SYS_FLEXE_UNUSED_FLAG_U8;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &txoutput, flexe_shim_id, entry);

        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &txoutput));
    }
    /********************TxSelOutputMapRam_t********************/
    CTC_ERROR_RETURN(_sys_tmm_flexe_cross_get_banksel_config(lchip, flexe_shim_id, SYS_FLEXE_DIR_TX, &cross_txbs));
    CTC_ERROR_RETURN(_sys_tmm_flexe_cross_set_banksel_config(lchip, flexe_shim_id, SYS_FLEXE_DIR_TX, !cross_txbs));

    /********************TxSelSchEntryRam_t********************/
    tbl_id = TxSelSchEntryRam_t;
    for (cycle = 0; cycle < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); cycle++)
    {
        entry = cycle / 2;
        index = DRV_INS(flexe_shim_id, entry);

        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &txsel_sch));

        val32 = 0xff;
        step_f = TxSelSchEntryRam_chIdOdd_f - TxSelSchEntryRam_chIdEven_f;
        factor_f = cycle%2;
        fld_id = TxSelSchEntryRam_chIdEven_f + step_f*factor_f;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &txsel_sch, flexe_shim_id, entry);

        val32 = 1;
        fld_id = TxSelSchEntryRam_flowIdEven_f;
        step_f = TxSelSchEntryRam_flowIdOdd_f - TxSelSchEntryRam_flowIdEven_f;
        factor_f = cycle%2;
        fld_id = TxSelSchEntryRam_flowIdEven_f + step_f*factor_f;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &txsel_sch, flexe_shim_id, entry);

        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &txsel_sch));
    }
    /********************TxSelSchEntryRam_t********************/

    /********************TxSelOutputMapRam_t********************/
    tbl_id = TxSelOutputMapRam_t;
    for (cycle = 0; cycle < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); cycle++)
    {
        entry = cycle / 2;
        index = DRV_INS(flexe_shim_id, entry);
        step_f = TxSelOutputMapRam_slotChIdOdd_f - TxSelOutputMapRam_slotChIdEven_f;
        factor_f = cycle%2;
        fld_id = TxSelOutputMapRam_slotChIdEven_f + step_f*factor_f;

        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &txoutput));

        val32 = 0xff;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &txoutput, flexe_shim_id, entry);

        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &txoutput));
    }
    /********************TxSelOutputMapRam_t********************/
    CTC_ERROR_RETURN(_sys_tmm_flexe_cross_set_banksel_config(lchip, flexe_shim_id, SYS_FLEXE_DIR_TX, cross_txbs));

    /********************RxSelOutputMapRam_t********************/
    tbl_id = RxSelOutputMapRam_t;
    for (id = 0; id < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); id++)
    {
        entry = id / 2;
        index = DRV_INS(flexe_shim_id, entry);
        step_f = RxSelOutputMapRam_slotChIdOdd_f - RxSelOutputMapRam_slotChIdEven_f;
        factor_f = id%2;
        fld_id = RxSelOutputMapRam_slotChIdEven_f + step_f*factor_f;

        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rxoutput));
        if (id < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CLIENT))
        {
            val32 = id;
        }
        else
        {
            val32 = 0xff;
        }
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &rxoutput, flexe_shim_id, entry);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rxoutput));
    }
    /********************RxSelOutputMapRam_t********************/

    CTC_ERROR_RETURN(_sys_tmm_flexe_cross_get_banksel_config(lchip, flexe_shim_id, SYS_FLEXE_DIR_RX, &cross_rxbs));
    CTC_ERROR_RETURN(_sys_tmm_flexe_cross_set_banksel_config(lchip, flexe_shim_id, SYS_FLEXE_DIR_RX, !cross_rxbs));

    /********************RxSelOutputMapRam_t********************/
    for (id = 0; id < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CLIENT); id++)
    {
        entry = id / 2;
        index = DRV_INS(flexe_shim_id, entry);
        step_f = RxSelOutputMapRam_slotChIdOdd_f - RxSelOutputMapRam_slotChIdEven_f;
        factor_f = id%2;
        fld_id = RxSelOutputMapRam_slotChIdEven_f + step_f*factor_f;

        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rxoutput));
        val32 = id;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &rxoutput, flexe_shim_id, entry);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rxoutput));
    }
    /********************RxSelOutputMapRam_t********************/

    CTC_ERROR_RETURN(_sys_tmm_flexe_cross_set_banksel_config(lchip, flexe_shim_id, SYS_FLEXE_DIR_RX, cross_rxbs));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_cross_chanmap_init(uint8 lchip, uint8 flexe_shim_id)
{
    uint8  i      = 0;
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0; 
    uint32 val32  = 0;

    FlexeTxChanMap_m tx_chanmap;
    FlexeRxChanMap_m rx_chanmap;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /********************* FlexeTxChanMap start! ***********************/

    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CLIENT); i++)
    {
    /* #1, calc index */
        index = DRV_INS(flexe_shim_id, i);

        /* #2.1, read HW table */
        tbl_id = FlexeTxChanMap_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_chanmap));

        /* ##2.3. modify field value */
        fld_id = FlexeTxChanMap_cfgMcMacTxChan_f;
        val32 = 0x3f;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &tx_chanmap, flexe_shim_id, i);

        fld_id = FlexeTxChanMap_cfgMcMacTxSel_f;
        val32 = 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &tx_chanmap, flexe_shim_id, i);

       /* #3, write HW table*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_chanmap));
        /********************* FlexeTxChanMap end! ***********************/

        /********************* FlexeRxChanMap start! ***********************/
        /* #2.1, read HW table */
        tbl_id = FlexeRxChanMap_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_chanmap));

        /* ##2.3. modify field value */
        fld_id = FlexeRxChanMap_cfgMcMacRxChan_f;
        val32 = 0x3f;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &rx_chanmap, flexe_shim_id, i);

        fld_id = FlexeRxChanMap_cfgMcMacRxSel_f;
        val32 = 0; /* CS0 or CS1 select */
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &rx_chanmap, flexe_shim_id, i);

       /* #3, write HW table*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_chanmap));
        /********************* FlexeRxChanMap end! ***********************/
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_cr_ca_init(uint8 lchip, uint8 flexe_shim_id)
{
    uint32          cmd   = 0;
    uint32          index = 0;
    uint32          step  = 0;
    uint32          factor = 0;
    uint32          tbl_id = 0;
    uint32          fld_id = 0;
    uint32          val32  = 0;
    uint8           i = 0;
    RxCtlInst0_m    rx_ctl;
    TxCtlInst0_m    tx_ctl;
    TxOhCalSwitchCfgInst0_m  tx_cal;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /*************** TxCtlInst0 start! ****************/
    /* #1, calc index */
    index = DRV_INS(flexe_shim_id, 0);

    step = RxCtlInst1_t - RxCtlInst0_t;
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        factor = i;
        tbl_id = RxCtlInst0_t;
        tbl_id += step*factor;

        /* #2, read HW table */
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_ctl));

        /* ##2.2. modify field value */
        /* ###2.2.1. */
        fld_id = RxCtlInst0_disableRxCaCalSwitch_f;
        val32 = 1;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &rx_ctl, flexe_shim_id, 0);

        /* #3, write HW table*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_ctl));
    }

    step = TxCtlInst1_t - TxCtlInst0_t;
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        factor = i;
        tbl_id = TxCtlInst0_t;
        tbl_id += step*factor;

        /* #2, read HW table */
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_ctl));

        /* ##2.2. modify field value */
        /* ###2.2.1. */
        fld_id = TxCtlInst0_disableTxCaCalSwitch_f;
        val32 = 1;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &tx_ctl, flexe_shim_id, 0);

        /* #3, write HW table*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_ctl));
    }

    step = TxOhCalSwitchCfgInst1_t - TxOhCalSwitchCfgInst0_t;
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        factor = i;
        tbl_id = TxOhCalSwitchCfgInst0_t;
        tbl_id += step*factor;

        /* #2, read HW table */
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_cal));

        /* ##2.2. modify field value */
        /* ###2.2.1. */
        fld_id = TxOhCalSwitchCfgInst0_calSwitchReq_f;
        val32 = 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &tx_cal, flexe_shim_id, 0);

        /* #3, write HW table*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_cal));
    }

    /*************** TxCtlInst0 end! ****************/

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_phyinst_bitmap_init(uint8 lchip, uint8 cs_id)
{
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;
    McPcsX8LanesMiscCfg_m    pcs_misc;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /*************** (II) McPcsX8LanesMiscCfg start! ****************/
    tbl_id = McPcsX8LanesMiscCfg_t;
    index = DRV_INS(cs_id, 0); 

    /* #2, read HW table */
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    fld_id = McPcsX8LanesMiscCfg_cfgMcPcsFlexeInstEnBmp_f;
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_misc));
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &pcs_misc);
    val32 = 0;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_misc, cs_id, 0);
    /* #3, write HW table*/
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_misc));

    /*************** (II) McPcsX8LanesMiscCfg end! ****************/

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_pcs_cal_init(uint8 lchip, uint8 cs_id)
{
    const uint32 walk_end = 7; /* walker end is always 7*/
    uint8  cal_entry[8] = {0, 4, 2, 6, 1, 5, 3, 7};
    uint32 val_32 = 0;
    uint32 cmd = 0;
    uint32 index = 0;
    int32  i = 0;
    uint32 table = 0;
    uint32 field = 0;

    McPcsX8LanesTxCal_m       pcs_entry;
    McPcsX8LanesTxCalCtrl_m   cal_ctl;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /* entry */ 
    table = McPcsX8LanesTxCal_t;
    field = McPcsX8LanesTxCal_calEntry_f;

    for (i = 0; i <= walk_end; i++)
    {
        index = DRV_INS(cs_id, i);
        cmd = DRV_IOR(table, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_entry));

        val_32 = cal_entry[i];

        DRV_IOW_FIELD_NZ(lchip, table, field, &val_32, &pcs_entry, cs_id, i);

        cmd = DRV_IOW(table, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_entry));
    }

    /* WalkerEnd */
    index = DRV_INS(cs_id, 0);
    cmd = DRV_IOR(McPcsX8LanesTxCalCtrl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cal_ctl));
    val_32 = walk_end;
    field = McPcsX8LanesTxCalCtrl_cfgWalkerEnd_f;
    DRV_IOW_FIELD_NZ(lchip, McPcsX8LanesTxCalCtrl_t, field, &val_32, &cal_ctl, cs_id, 0);

    cmd = DRV_IOW(McPcsX8LanesTxCalCtrl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cal_ctl));

    /* Tx ready */
    index = DRV_INS(cs_id, 0);
    cmd = DRV_IOR(McPcsX8LanesTxCalCtrl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cal_ctl));
    val_32 = 1;
    DRV_IOW_FIELD_NZ(lchip, McPcsX8LanesTxCalCtrl_t, McPcsX8LanesTxCalCtrl_cfgMcPcsTxReady_f, &val_32, &cal_ctl, cs_id, 0);
    cmd = DRV_IOW(McPcsX8LanesTxCalCtrl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cal_ctl));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_macrx_cal_init(uint8 lchip, uint8 txqm_id)
{
    uint32 val_32 = 0;
    uint32 walkend = 0;
    uint32 cmd = 0;
    uint32 index = 0;
    int32  i = 0;
    uint32 table = 0;
    uint32 field = 0;
    McMacRxCal_m      macrx_cal;
    McMacCalCtrl_m    cal_ctrl;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    index = DRV_INS(txqm_id, 0);
    cmd = DRV_IOR(McMacCalCtrl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cal_ctrl));

    /* WalkerEnd */
    field = McMacCalCtrl_cfgRxWalkerEnd_f;
    DRV_IOW_FIELD_NZ(lchip, McMacCalCtrl_t, field, &walkend, &cal_ctrl, txqm_id, 0);
    field = McMacCalCtrl_cfgRxWalkerEndBak_f;
    DRV_IOW_FIELD_NZ(lchip, McMacCalCtrl_t, field, &walkend, &cal_ctrl, txqm_id, 0);
    cmd = DRV_IOW(McMacCalCtrl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cal_ctrl));

    /***************** Mac Rx Cal *********************/
    /* calEntry */
    table = McMacRxCal_t;
    field = McMacRxCal_calEntry_f;
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); i++)
    {
        index = DRV_INS(txqm_id, i);
        cmd = DRV_IOR(table, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macrx_cal));
        val_32 = 0x3f;
        DRV_IOW_FIELD_NZ(lchip, table, field, &val_32, &macrx_cal, txqm_id, i);
        cmd = DRV_IOW(table, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macrx_cal));
    }

    table = McMacRxCalBak_t;
    field = McMacRxCalBak_calEntry_f;
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); i++)
    {
        index = DRV_INS(txqm_id, i);
        cmd = DRV_IOR(table, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macrx_cal));
        val_32 = 0x3f;
        DRV_IOW_FIELD_NZ(lchip, table, field, &val_32, &macrx_cal, txqm_id, i);
        cmd = DRV_IOW(table, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &macrx_cal));
    }

    /* Rx ready */
    index = DRV_INS(txqm_id, 0);
    cmd = DRV_IOR(McMacCalCtrl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cal_ctrl));
    val_32 = 1;
    DRV_IOW_FIELD_NZ(lchip, McMacCalCtrl_t, McMacCalCtrl_cfgMcMacRxReady_f, &val_32, &cal_ctrl, txqm_id, 0);
    cmd = DRV_IOW(McMacCalCtrl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cal_ctrl));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_macrx_chanmap_init(uint8 lchip, uint8 txqm_id)
{
    uint32          mcmac_id = 0;
    uint32          tbl_id = 0;
    uint32          fld_id = 0;
    uint32          cmd   = 0;
    uint32          index = 0;
    uint32          val32  = 0;
    McMacRxChanMap_m rxchan;

    for (mcmac_id = 0; mcmac_id < SYS_TMM_MAX_MAC_NUM_PER_TXQM; mcmac_id++)
    {
        index = DRV_INS(txqm_id, mcmac_id);
        tbl_id = McMacRxChanMap_t;
        fld_id = McMacRxChanMap_chanMap_f;

        /* #2, read HW table */
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rxchan));

        /* ##2.2. modify field value */
        /* ###2.2.1. */
        val32 = mcmac_id;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &rxchan, txqm_id, mcmac_id);

        /* #3, write HW table*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rxchan));
    }

    return CTC_E_NONE;
}

int32
_sys_tmm_flexe_set_hata_cfg(uint8 lchip, uint8 txqm_id, uint8 dir, uint8 enable)
{
    uint8  i          = 0;
    uint32 tbl_id     = 0;
    uint32 fld_id     = 0;
    uint32 cmd        = 0;
    uint32 index      = 0;
    uint32 array32[2] = {0};
    McHataSoftResetCfg_m hata_rst;
    McHataEnable_m       hata_en;
    McMacMacRxCfg_m      mcmac_cfg;

    /*McHataSoftResetCfg_cfgMcHataRxSoftReset_f*/
    /*McHataSoftResetCfg_cfgMcHataTxSoftReset_f*/
    tbl_id = McHataSoftResetCfg_t;
    fld_id = (SYS_FLEXE_DIR_RX == dir) ? \
       McHataSoftResetCfg_cfgMcHataRxSoftReset_f : \
       McHataSoftResetCfg_cfgMcHataTxSoftReset_f;

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    index = DRV_INS(txqm_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hata_rst));
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, array32, &hata_rst);
    if(!enable)
    {
        array32[1] = 0xffffffff;
        array32[0] = 0xffffffff;
    }
    else
    {
        array32[1] = 0xffffff00;
        array32[0] = 0;
    }
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, array32, &hata_rst, txqm_id, 0);

    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hata_rst));
    if(!enable)
    {
        return CTC_E_NONE;
    }

    /*McHataEnable_cfgHataTxEnable_f*/
    /*McHataEnable_cfgHataRxEnable_f*/
    tbl_id = McHataEnable_t;
    fld_id = (SYS_FLEXE_DIR_RX == dir) ? \
       McHataEnable_cfgHataRxEnable_f : \
       McHataEnable_cfgHataTxEnable_f;

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    index = DRV_INS(txqm_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hata_en));
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, array32, &hata_en);
    array32[1] &= 0xffffff00;
    array32[0] = 0;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, array32, &hata_en, txqm_id, 0);

    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hata_en));

    /* McMacMacRxCfg, cfgMcMacMacRx_[0..39]_cfgMcMacRxUseHataTsEn */
    tbl_id = McMacMacRxCfg_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    index = DRV_INS(txqm_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mcmac_cfg));

    for (i = 0; i < SYS_TMM_MAX_MAC_NUM_PER_TXQM; i++)
    {
        fld_id = McMacMacRxCfg_cfgMcMacMacRx_0_cfgMcMacRxUseHataTsEn_f;
        fld_id += i*(McMacMacRxCfg_cfgMcMacMacRx_1_cfgMcMacRxUseHataTsEn_f - McMacMacRxCfg_cfgMcMacMacRx_0_cfgMcMacRxUseHataTsEn_f);
        array32[0] = 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &array32[0], &mcmac_cfg, txqm_id, 0);
    }

    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mcmac_cfg));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_mcmac_rsv_cfg(uint8 lchip, uint16 mac_id, uint8 enable)
{
    uint32          cmd   = 0;
    uint32          txqm  = 0;
    uint32          index = 0;
    uint32          tbl_id = 0;
    uint32          fld_id = 0;
    uint32          val32  = 0;
    uint16          inner_mac_id = TXQM_INNER_MAC_ID(mac_id);
    McMacReserved_m    mac_rsv;

    if (SYS_FLEXE_UNUSED_FLAG_U16 == mac_id)
    {
        return CTC_E_NONE;
    }

    /***************  McMacReserved start! ****************/
    /* #1, calc index */
    txqm = mac_id / SYS_TMM_MAX_MAC_NUM_PER_TXQM;
    index = DRV_INS(txqm, 0);

    /* #2, read HW table */
    tbl_id = McMacReserved_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mac_rsv));

    if (inner_mac_id < 32)
    {
        fld_id = McMacReserved_mcMacReserved_0_reserved_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &mac_rsv);
        if (enable)
        {
            val32 &= ~(1 << inner_mac_id);
        }
        else
        {
            val32 |= (1 << inner_mac_id);
        }
    }
    else
    {
        fld_id = McMacReserved_mcMacReserved_1_reserved_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &mac_rsv);
        if (enable)
        {
            val32 &= ~(1 << (inner_mac_id % 8));
        }
        else
        {
            val32 |= (1 << (inner_mac_id % 8));
        }
    }
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mac_rsv, txqm, 0);

    /* #3, write HW table*/
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mac_rsv));
    /***************  McMacReserved end! ****************/

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_mac_rsv_cfg(uint8 lchip, uint8 txqm_id, uint8 enable)
{
    uint32          cmd   = 0;
    uint32          index = 0;
    uint32          tbl_id = 0;
    uint32          fld_id = 0;
    uint32          val32  = 0;
    McMacReserved_m    mac_rsv;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /*************** (I) McMacReserved start! ****************/
    /* #1, calc index */
    index = DRV_INS(txqm_id, 0);

    /* #2, read HW table */
    tbl_id = McMacReserved_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mac_rsv));

    fld_id = McMacReserved_mcMacReserved_0_reserved_f;
    val32 = enable ? 0xffffffff : 0;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mac_rsv, txqm_id, 0);
    fld_id = McMacReserved_mcMacReserved_1_reserved_f;
    val32 = enable ? 0xff : 0;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mac_rsv, txqm_id, 0);

    /* #3, write HW table*/
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mac_rsv));
    /*************** (I) McMacReserved end! ****************/

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_misc_init(uint8 lchip, uint8 cs_id)
{
    uint32          cmd   = 0;
    uint32          index = 0;
    uint32          tbl_id = 0;
    uint32          fld_id = 0;
    uint32          val32  = 0;
    RefDivMcMacPulse_m mac_pulse;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /*************** (I) RefDivMcMacPulse start! ****************/
    /* #1, calc index */
    index = DRV_INS(0, 0);

    /* #2, read HW table */
    tbl_id = RefDivMcMacPulse_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mac_pulse));

    switch (cs_id)
    {
    case 0:
        fld_id = RefDivMcMacPulse_cfgResetDivMcMac2Dp0SgmacPauseTimer3Pulse_f;
        break;
    case 1:
        fld_id = RefDivMcMacPulse_cfgResetDivMcMac3Dp0SgmacPauseTimer3Pulse_f;
        break;
    case 2:
        fld_id = RefDivMcMacPulse_cfgResetDivMcMac2Dp1SgmacPauseTimer3Pulse_f;
        break;
    case 3:
        fld_id = RefDivMcMacPulse_cfgResetDivMcMac3Dp1SgmacPauseTimer3Pulse_f;
        break;
    }

    val32 = 0;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mac_pulse, 0, 0);

    /* #3, write HW table*/
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mac_pulse));
    /*************** (I) RefDivMcMacPulse end! ****************/

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_bondmask_init(uint8 lchip, uint8 flexe_shim_id)
{
    uint32          cmd   = 0;
    uint32          index = 0;
    uint32          step  = 0;
    uint32          factor = 0;
    uint32          tbl_id = 0;
    uint32          fld_id = 0;
    uint32          val32  = 0;
    uint8           i = 0, j = 0;
    TxCtlInst0_m    inst_ctl;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /********************************************************************************************
     -- Config BondMask
       *  TxCtlInst0.bondMask : multi-instance bond to ONE group
       *  TxCtlInst0.padEn : instance conneted PHY type: 50G/200G/400G, padEN = 1; 100G, padEn = 0;
       *  RxCtlInst0.bondMask : multi-instance bond to ONE group
       *  RxCtlInst0.padEn : instance conneted PHY type: 50G/200G/400G, padEN = 1; 100G, padEn = 0;
    *********************************************************************************************/

    /*************** TxCtlInst0 start! ****************/
    /* #1, calc index */
    index = DRV_INS(flexe_shim_id, 0);

    step = TxCtlInst1_t - TxCtlInst0_t;
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        factor = i;
        for (j = 0; j < SYS_FLEXE_DIR_MAX; j++)
        {
            tbl_id = j ? RxCtlInst0_t : TxCtlInst0_t;
            tbl_id += step*factor;

            /* #2, read HW table */
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &inst_ctl));

            /* ##2.2. modify field value */
            /* ###2.2.1. */
            fld_id = TxCtlInst0_bondMask_f;
            val32 = 1 << i;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &inst_ctl, flexe_shim_id, 0);

            /* #3, write HW table*/
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &inst_ctl));
        }
    }
    /*************** TxCtlInst0 end! ****************/

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_rate_comp_writemask(uint8 lchip, uint8 flexe_shim_id, uint32 xc_chid, sys_flexe_client_flow_t flow_type, uint8 enable)
{
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 step   = 0;
    uint32 factor = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;
    McRateCompWriteMaskA0_m wm;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n[FlexE] %s @ %d, flexe_shim_id %d xc_chid %d, flow_type %d, enable %d\n", \
        __FUNCTION__, __LINE__, flexe_shim_id, xc_chid, flow_type, enable);

    index = DRV_INS(flexe_shim_id, 0);

    switch (flow_type)
    {
    case SYS_FLEXE_FLOW_TYPE_A:
        tbl_id = McRateCompWriteMaskA0_t;
        break;
    case SYS_FLEXE_FLOW_TYPE_C:
        tbl_id = McRateCompWriteMaskC0_t;
        break;
    default:
        tbl_id = McRateCompWriteMaskB0_t;
        break;
    }

    step = McRateCompWriteMaskA1_t - McRateCompWriteMaskA0_t;
    factor = (xc_chid > 31) ? 1 : 0;
    tbl_id += step*factor;

    fld_id = McRateCompWriteMaskA0_val_f ;

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &wm));
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &wm);
    if (enable)
    {
        if (xc_chid > 31)
        {
            val32 |= (1 << (xc_chid-32));
        }
        else
        {
            val32 |= (1 << xc_chid);
        }
    }
    else
    {
        if (xc_chid > 31)
        {
            val32 &= ~(1 << (xc_chid-32));
        }
        else
        {
            val32 &= ~(1 << xc_chid);
        }
    }

    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &wm, flexe_shim_id, 0);
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &wm));

    return CTC_E_NONE;
}

/* Now only support Flow B */
STATIC int32
_sys_tmm_flexe_mcfifo_writemask(uint8 lchip, uint8 flexe_shim_id, uint32 xc_chid, uint8 enable)
{
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 step   = 0;
    uint32 factor = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;
    McFifoWriteMask0_m wm;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n[FlexE] %s @ %d, flexe_shim_id %d xc_chid %d\n", \
        __FUNCTION__, __LINE__, flexe_shim_id, xc_chid);

    index = DRV_INS(flexe_shim_id, 0);

    tbl_id = McFifoWriteMask0_t;
    step = McFifoWriteMask1_t - McFifoWriteMask0_t;
    factor = (xc_chid > 31) ? 1 : 0;
    tbl_id += step*factor;

    fld_id = McFifoWriteMask0_val_f ;

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &wm));
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &wm);

    if (enable)
    {
        if (xc_chid > 31)
        {
            val32 |= (1 << (xc_chid-32));
        }
        else
        {
            val32 |= (1 << xc_chid);
        }
    }
    else
    {
        if (xc_chid > 31)
        {
            val32 &= ~(1 << (xc_chid-32));
        }
        else
        {
            val32 &= ~(1 << xc_chid);
        }
    }

    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &wm, flexe_shim_id, 0);
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &wm));

    return CTC_E_NONE;
}

int32 _sys_tmm_flexe_set_mcu_adjust_en(uint8 lchip, uint8 mcu_id, uint8 enable)
{
    uint32 val32 = 0;

    val32 = enable ? FLEXE_ADJ_MODE : NORMAL_MODE;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "mcu_id is %d, and enable is %d\n", mcu_id, enable);

    CTC_ERROR_RETURN(sys_tmm_mcu_write_shared_memory(lchip,      mcu_id, GLB_INFO_SW_MODE, 0x0, val32));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_mgr_init(uint8 lchip, uint8 flexe_shim_id, uint8 enable)
{
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;
    FlexeMgrRxMacCfg_m  rx_mac_cfg;
    FlexeMgrOhCfg_m     oh_cfg;
    FlexeMgrCfg_m       mgr_cfg;
    FlexeMgrTsCfg_m     ts_cfg;

    /* FlexeMgrRxMacCfg begin */
    tbl_id = FlexeMgrRxMacCfg_t;
    index = DRV_INS(flexe_shim_id, 0);

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_mac_cfg));

    val32 = enable ? 7 : 0;
    fld_id = FlexeMgrRxMacCfg_cfgRxCaptureOhFrameCnt_f;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &rx_mac_cfg, flexe_shim_id, 0);

    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_mac_cfg));
    /* FlexeMgrRxMacCfg end */

    /* FlexeMgrOhCfg begin */
    tbl_id = FlexeMgrOhCfg_t;
    index = DRV_INS(flexe_shim_id, 0);

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &oh_cfg));

    val32 = 0;
    fld_id = FlexeMgrOhCfg_cfgTxChanEn_f;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &oh_cfg, flexe_shim_id, 0);
    fld_id = FlexeMgrOhCfg_cfgTxOhEn_f;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &oh_cfg, flexe_shim_id, 0);
    fld_id = FlexeMgrOhCfg_cfgRxOhEn_f;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &oh_cfg, flexe_shim_id, 0);

    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &oh_cfg));
    /* FlexeMgrOhCfg end */

    /* FlexeMgrCfg begin */
    tbl_id = FlexeMgrCfg_t;
    index = DRV_INS(flexe_shim_id, 0);

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mgr_cfg));

    val32 = enable ? flexe_shim_id : 0;
    fld_id = FlexeMgrCfg_cfgFlexeDpId_f;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mgr_cfg, flexe_shim_id, 0);

    val32 = 0;
    fld_id = FlexeMgrCfg_cfgFlexeMgr100gInst_f;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mgr_cfg, flexe_shim_id, 0);

    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mgr_cfg));
    /* FlexeMgrCfg end */

    /* FlexeMgrTsCfg begin */
    tbl_id = FlexeMgrTsCfg_t;
    index = DRV_INS(flexe_shim_id, 0);

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ts_cfg));

    val32 = enable ? 0x000000ff : 0;
    fld_id = FlexeMgrTsCfg_cfgTxTsCaptureMode_f;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &ts_cfg, flexe_shim_id, 0);
    fld_id = FlexeMgrTsCfg_cfgRxTsCaptureMode_f;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &ts_cfg, flexe_shim_id, 0);

    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ts_cfg));
    /* FlexeMgrTsCfg end */

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_mgr_ts_cfg(uint8 lchip, sys_flexe_group_t* group_node, uint8 enable)
{
    uint8 i = 0 , j = 0;
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;
    uint32 step   = 0;
    uint32 factor = 0;
    uint32 cs_id  = 0;
    uint8 phy_speed          = 0;
    uint8 flexe_shim_id      = 0;
    uint8 phy_inst_cnt       = 0;
    uint8 physical_serdes_id = 0; /* physical serdes id of phy_base */
    sys_flexe_phy_t*   p_phy = NULL;
    FlexeMgrTsCfg_m  cm;

    flexe_shim_id = group_node->flexe_shim_id;
    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &phy_speed);
    phy_inst_cnt = SYS_TMM_FLEXE_PHY_2_INST_CNT(phy_speed);

    tbl_id = FlexeMgrTsCfg_t;
    index = DRV_INS(flexe_shim_id, 0);
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));

    for (i = 0; i < group_node->phy_cnt; i++)
    {
        p_phy = &group_node->phy_list[i];
        SYS_TMM_FLEXE_SERDES_2_CS(p_phy->logical_serdes_base, cs_id);
        _sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, p_phy->logical_serdes_base, &physical_serdes_id);
                SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == physical_serdes_id), CTC_E_INVALID_PARAM);

        for (j = 0; j < phy_inst_cnt; j++)
        {
            /* New value */
            val32 = (enable && (cs_id % 2)) ? 1 : 0;
            factor = p_phy->inst_base+j;
            step = FlexeMgrTsCfg_cfgRxPmSel_1_rxSelMcPcs_f - FlexeMgrTsCfg_cfgRxPmSel_0_rxSelMcPcs_f;
            fld_id = FlexeMgrTsCfg_cfgRxPmSel_0_rxSelMcPcs_f + step*factor;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &cm, flexe_shim_id, 0);

            step = FlexeMgrTsCfg_cfgTxPmSel_1_txSelMcPcs_f - FlexeMgrTsCfg_cfgTxPmSel_0_txSelMcPcs_f;
            fld_id = FlexeMgrTsCfg_cfgTxPmSel_0_txSelMcPcs_f + step*factor;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &cm, flexe_shim_id, 0);

            step = FlexeMgrTsCfg_cfgTxPmLaneSel_1_txSelMcPcs_f - FlexeMgrTsCfg_cfgTxPmLaneSel_0_txSelMcPcs_f;
            fld_id = FlexeMgrTsCfg_cfgTxPmLaneSel_0_txSelMcPcs_f + step*factor;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &cm, flexe_shim_id, 0);

            /* New value */
            val32 = enable ? (physical_serdes_id % TMM_MAX_SERDES_NUM_PER_CS) : 0;  ///TODO: only one lane??
            step = FlexeMgrTsCfg_cfgTxPmLaneSel_1_txSelLane_f - FlexeMgrTsCfg_cfgTxPmLaneSel_0_txSelLane_f;
            fld_id = FlexeMgrTsCfg_cfgTxPmLaneSel_0_txSelLane_f + step*factor;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &cm, flexe_shim_id, 0);

            /* New value */
            val32 = enable ? (p_phy->logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS) : 0;  ///TODO: only one lane??
            step = FlexeMgrTsCfg_cfgRxPmSel_1_rxSelChan_f - FlexeMgrTsCfg_cfgRxPmSel_0_rxSelChan_f;
            fld_id = FlexeMgrTsCfg_cfgRxPmSel_0_rxSelChan_f + step*factor;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &cm, flexe_shim_id, 0);

            step = FlexeMgrTsCfg_cfgTxPmSel_1_txSelChan_f - FlexeMgrTsCfg_cfgTxPmSel_0_txSelChan_f;
            fld_id = FlexeMgrTsCfg_cfgTxPmSel_0_txSelChan_f + step*factor;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &cm, flexe_shim_id, 0); 

            /* New value */
            if (enable)
            {
                switch (phy_speed)
                {
                case CTC_PORT_SPEED_50G:
                    val32 = 8;
                    break;
                case CTC_PORT_SPEED_100G:
                    val32 = 9;
                    break;
                case CTC_PORT_SPEED_200G:
                    val32 = 10;
                    break;
                case CTC_PORT_SPEED_400G:
                    val32 = 11;
                    break;
                default:
                    val32 = 0;
                    break;
                }
            }
            else
            {
                val32 = 0;
            }
            step = FlexeMgrTsCfg_cfgPhyModeSel_1_speed_f - FlexeMgrTsCfg_cfgPhyModeSel_0_speed_f;
            fld_id = FlexeMgrTsCfg_cfgPhyModeSel_0_speed_f + step*factor;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &cm, flexe_shim_id, 0);
        }
    }

    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));

    return CTC_E_NONE;
}



STATIC int32
_sys_tmm_flexe_mgr_oh_cfg(uint8 lchip, sys_flexe_group_t* group_node, uint8 enable)
{
    uint8  i             = 0;
    uint8  j             = 0;
    uint32 tbl_id        = 0;
    uint32 fld_id        = 0;
    uint32 cmd           = 0;
    uint32 index         = 0;
    uint32 val32         = 0;
    uint8  inst_id       = 0;
    uint8  phy_speed     = 0;
    uint8  flexe_shim_id = 0;
    FlexeMgrOhCfg_m  cm;

    flexe_shim_id = group_node->flexe_shim_id;
    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &phy_speed);

    tbl_id = FlexeMgrOhCfg_t;
    index = DRV_INS(flexe_shim_id, 0);
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));

    /* Field #1 begin */
    for (i = 0; i < SYS_FLEXE_DIR_MAX; i++)
    {
        fld_id = ((SYS_FLEXE_DIR_RX == i) ? FlexeMgrOhCfg_cfgRxOhEn_f : FlexeMgrOhCfg_cfgTxOhEn_f);
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &cm);

        for (j = 0; j < group_node->inst_cnt; j++)
        {
            inst_id = group_node->inst_list[j];
            val32 &= ~(1 << inst_id);
            SYS_CONDITION_CONTINUE(!enable);
            if ((CTC_PORT_SPEED_50G == phy_speed) || \
                ((CTC_PORT_SPEED_50G != phy_speed) && !(inst_id%2)))
            {
                val32 |= (1 << inst_id);
            }
        }
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &cm, flexe_shim_id, 0);
    }
    /* Field #1 end */

    /* Field #2 begin */
    fld_id = FlexeMgrOhCfg_cfgTxChanEn_f;
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &cm);
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        inst_id = group_node->inst_list[i];

        val32 &= ~(1 << inst_id);    /* section2section */
        val32 &= ~(1 << (8+inst_id));    /* sync */
        val32 &= ~(1 << (16+inst_id));   /* shim2shim */

        SYS_CONDITION_CONTINUE(!enable);
        if ((CTC_PORT_SPEED_50G == phy_speed) || \
            ((CTC_PORT_SPEED_50G != phy_speed) && !(inst_id%2)))
        {
            val32 |= (1 << inst_id);    /* section2section */
            val32 |= (1 << (8+inst_id));    /* sync */
            val32 |= (1 << (16+inst_id));   /* shim2shim */
        }
    }
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &cm, flexe_shim_id, 0);
    /* Field #2 end */

    /* Field #3/#4/#5 begin */
    for (i = 0; i < 3; i++)
    {
        fld_id = (0 == i) ? FlexeMgrOhCfg_cfgRxOhSectionEn_f : \
            ((1 == i) ? FlexeMgrOhCfg_cfgRxOhSyncEn_f : FlexeMgrOhCfg_cfgRxOhShim2ShimEn_f);
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &cm);

        for (j = 0; j < group_node->inst_cnt; j++)
        {
            inst_id = group_node->inst_list[j];
            val32 &= ~(1 << inst_id);
            SYS_CONDITION_CONTINUE(!enable);
            if ((CTC_PORT_SPEED_50G == phy_speed) || \
                ((CTC_PORT_SPEED_50G != phy_speed) && !(inst_id%2)))
            {
                val32 |= (1 << inst_id);
            }
        }
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &cm, flexe_shim_id, 0);
    }
    /* Field #3/#4/#5 end */

    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_mgr_rxmac_cfg(uint8 lchip, sys_flexe_group_t* group_node, uint8 enable)
{
    uint8  i      = 0;
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;
    uint32 step   = 0;
    uint8 inst_id = 0;
    uint8 phy_speed        = 0;
    uint8 flexe_shim_id    = 0;
    FlexeMgrRxMacCfg_m  cm;

    flexe_shim_id = group_node->flexe_shim_id;
    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &phy_speed);

    tbl_id = FlexeMgrRxMacCfg_t;
    index = DRV_INS(flexe_shim_id, 0);
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        inst_id = group_node->inst_list[i];
        step = FlexeMgrRxMacCfg_cfgRxCaptureOhMfCnt1_f - FlexeMgrRxMacCfg_cfgRxCaptureOhMfCnt0_f;
        fld_id = FlexeMgrRxMacCfg_cfgRxCaptureOhMfCnt0_f + step*inst_id;

        if (enable)
        {
            if (CTC_PORT_SPEED_50G == phy_speed)
            {
                val32 = 15;
            }
            else 
            {
                val32 = 31;
            }
        }
        else
        {
            val32 = 0;
        }
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &cm, flexe_shim_id, 0);
    }
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_inst_rpf_en(uint8 lchip, uint8 flexe_shim_id, uint8 asic_inst, uint8 rpf_en)
{
    uint32 tbl_id           = 0;
    uint32 fld_id           = 0;
    uint32 cmd              = 0;
    uint32 index            = 0;
    uint32 val32            = 0;
    uint32 step             = 0;
    uint32 factor           = 0;

    FlexeMgrTsCfg_m  mgr_tscfg;

    /* #1, calc index */
    index = DRV_INS(flexe_shim_id, 0);

    /* #2, read HW table */
    tbl_id = FlexeMgrTsCfg_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mgr_tscfg));

    /* #3. modify field value */
    if (0 == asic_inst % 2)
    {
        factor = 4 + asic_inst / 2;
        step = FlexeMgrTsCfg_cfgPhyModeSel_1_pmaMode_f - FlexeMgrTsCfg_cfgPhyModeSel_0_pmaMode_f;
        fld_id = FlexeMgrTsCfg_cfgPhyModeSel_0_pmaMode_f + step*factor;
    }
    else
    {
        factor = 4 + asic_inst / 2;
        step = FlexeMgrTsCfg_cfgPhyModeSel_1_pam4Mode_f - FlexeMgrTsCfg_cfgPhyModeSel_0_pam4Mode_f;
        fld_id = FlexeMgrTsCfg_cfgPhyModeSel_0_pam4Mode_f + step*factor;
    }
    val32 = rpf_en ? 1 : 0;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mgr_tscfg, flexe_shim_id, 0);

    /* #4, write HW table */
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mgr_tscfg));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_inst_rpf_val(uint8 lchip, uint8 flexe_shim_id, uint8 asic_inst, uint8 rpf_val)
{
    uint32 tbl_id           = 0;
    uint32 fld_id           = 0;
    uint32 cmd              = 0;
    uint32 index            = 0;
    uint32 val32            = 0;
    uint32 step             = 0;
    uint32 factor           = 0;
    FlexeMgrTsCfg_m  mgr_tscfg;

    /* #1, calc index */
    index = DRV_INS(flexe_shim_id, 0);

    /* #2, read HW table */
    tbl_id = FlexeMgrTsCfg_t;
    factor = asic_inst / 2;
    step = FlexeMgrTsCfg_cfgPhyModeSel_1_rsFecMode_f - FlexeMgrTsCfg_cfgPhyModeSel_0_rsFecMode_f;
    fld_id = FlexeMgrTsCfg_cfgPhyModeSel_0_rsFecMode_f + step*factor;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mgr_tscfg));
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &mgr_tscfg);

    /* #3. modify field value */
    if(rpf_val)
    {
        val32 |= (1 << (asic_inst % 2));
    }
    else
    {
        val32 &= ~(1 << (asic_inst % 2));
    }
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mgr_tscfg, flexe_shim_id, 0);

    /* #4, write HW table */
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mgr_tscfg));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_en_cfg(uint8 lchip, uint8 flexe_shim_id, uint8 enable)
{
    uint8  i = 0;
    uint32 tbl_id = 0;
    uint32 index = 0;
    uint32 cmd = 0;
    uint32 val32 = 0;
    RxIntMaskInst0_m flex_mask_rx;

    index = DRV_INS(flexe_shim_id, 0);

    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        tbl_id = RxIntMaskInst0_t;
        tbl_id += (RxIntMaskInst1_t - RxIntMaskInst0_t)*i;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &flex_mask_rx));

        val32 = 0;
        SetRxIntMaskInst0(V, RPF_f,            &flex_mask_rx, val32);
        SetRxIntMaskInst0(V, cBitErr_f,        &flex_mask_rx, val32);
        SetRxIntMaskInst0(V, calChangeAck_f,   &flex_mask_rx, val32);
        SetRxIntMaskInst0(V, calChangeReq_f,   &flex_mask_rx, val32);
        SetRxIntMaskInst0(V, calSwitchEv_f,    &flex_mask_rx, val32);
        SetRxIntMaskInst0(V, chIdCfgErr_f,     &flex_mask_rx, val32);
        SetRxIntMaskInst0(V, chanFifoErr_f,    &flex_mask_rx, val32);
        SetRxIntMaskInst0(V, crcErr_f,         &flex_mask_rx, val32);
        SetRxIntMaskInst0(V, deskewOverflow_f, &flex_mask_rx, val32);
        SetRxIntMaskInst0(V, deskew_f,         &flex_mask_rx, val32);
        SetRxIntMaskInst0(V, lossOhLock_f,     &flex_mask_rx, val32);
        SetRxIntMaskInst0(V, lossOhMfLock_f,   &flex_mask_rx, val32);
        SetRxIntMaskInst0(V, ohLock_f,         &flex_mask_rx, val32);
        SetRxIntMaskInst0(V, ohMfLock_f,       &flex_mask_rx, val32);
        SetRxIntMaskInst0(V, ohMfReceived_f,   &flex_mask_rx, val32);
        SetRxIntMaskInst0(V, padLock_f,        &flex_mask_rx, val32);

        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &flex_mask_rx));
    }

    if (enable)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_soc_en(lchip, flexe_shim_id, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_cross_en(lchip, flexe_shim_id, SYS_FLEXE_DIR_TX, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_cross_en(lchip, flexe_shim_id, SYS_FLEXE_DIR_RX, TRUE));
        for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_set_inst_en(lchip, flexe_shim_id, i, SYS_FLEXE_DIR_TX, TRUE));
            CTC_ERROR_RETURN(_sys_tmm_flexe_set_inst_en(lchip, flexe_shim_id, i, SYS_FLEXE_DIR_RX, TRUE));
        }

        CTC_ERROR_RETURN(_sys_tmm_flexe_bondmask_init(lchip, flexe_shim_id));
        CTC_ERROR_RETURN(_sys_tmm_flexe_cross_init(lchip, flexe_shim_id));
        CTC_ERROR_RETURN(_sys_tmm_flexe_cross_chanmap_init(lchip, flexe_shim_id));
        CTC_ERROR_RETURN(_sys_tmm_flexe_cr_ca_init(lchip, flexe_shim_id));
        CTC_ERROR_RETURN(_sys_tmm_flexe_ohram_clear(lchip, flexe_shim_id));

        /* control rpf by software */
        if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A))
        {
            for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
            {
                CTC_ERROR_RETURN(_sys_tmm_flexe_set_inst_rpf_val(lchip, flexe_shim_id, i, FALSE));
                CTC_ERROR_RETURN(_sys_tmm_flexe_set_inst_rpf_en(lchip, flexe_shim_id, i, TRUE));
            }
        }
    }
    else
    {
        for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_set_inst_en(lchip, flexe_shim_id, i, SYS_FLEXE_DIR_TX, FALSE));
            CTC_ERROR_RETURN(_sys_tmm_flexe_set_inst_en(lchip, flexe_shim_id, i, SYS_FLEXE_DIR_RX, FALSE));
        }
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_cross_en(lchip, flexe_shim_id, SYS_FLEXE_DIR_TX, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_cross_en(lchip, flexe_shim_id, SYS_FLEXE_DIR_RX, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_soc_en(lchip, flexe_shim_id, FALSE));
    }

    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CLIENT); i++)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_writemask(lchip, flexe_shim_id, i, SYS_FLEXE_FLOW_TYPE_A, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_writemask(lchip, flexe_shim_id, i, SYS_FLEXE_FLOW_TYPE_C, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_writemask(lchip, flexe_shim_id, i, SYS_FLEXE_FLOW_TYPE_B, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_mcfifo_writemask(lchip, flexe_shim_id, i, FALSE));
    }

    CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_init(lchip, flexe_shim_id, enable));

    CTC_ERROR_RETURN(_sys_tmm_flexe_set_mcu_adjust_en(lchip, (flexe_shim_id == 0 ? 2 : 5), enable));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_mac_send_en(uint8 lchip, uint8 txqm_id, uint8 enable)
{
    uint8 factor     = 0;
    uint32 index     = 0;
    uint32 tbl_id    = McMacMacTxCfg_t;
    uint32 cmd       = 0;
    uint32 fld_id    = 0;
    uint32 val32     = 0;
    uint32 step      = McMacMacTxCfg_cfgMcMacMacTx_1_cfgMcMacTxSendEn_f - McMacMacTxCfg_cfgMcMacMacTx_0_cfgMcMacTxSendEn_f;
    McMacMacTxCfg_m  mcmac_tx;

    index = DRV_INS(txqm_id, 0);

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mcmac_tx));
    val32 = enable ? 1 : 0;
    for (factor = 0; factor < SYS_TMM_MAX_MAC_NUM_PER_TXQM; factor ++)
    {
        fld_id = McMacMacTxCfg_cfgMcMacMacTx_0_cfgMcMacTxSendEn_f + step*factor;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mcmac_tx, txqm_id, 0);
    }
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mcmac_tx));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_mactx_portmap_init(uint8 lchip, uint8 txqm_id)
{
    uint8 i = 0;
    uint32 index  = 0;
    uint32 tbl_id = 0;
    uint32 cmd    = 0;
    uint32 fld_id = 0;
    uint32 val32  = 0;
    McMacTxPortMap_m port_map;

    for (i = 0; i < SYS_TMM_MAX_MAC_NUM_PER_TXQM; i++)
    {
        /*************** (V) McMacTxPortMap start! ****************/
        /* #1, calc index */
        index = DRV_INS(txqm_id, i);

        /* #2, read HW table: McMacTxPortMap */
        tbl_id = McMacTxPortMap_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &port_map));

        fld_id = McMacTxPortMap_portMap_f;
        val32 = 0x3f;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &port_map, txqm_id, i);

        /* #3, write HW table: McMacTxPortMap*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &port_map));
        /*************** (V) McMacTxPortMap end! ****************/
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_mactx_init(uint8 lchip, uint8 txqm_id)
{
    uint8 factor     = 0;
    uint32 index     = 0;
    uint32 tbl_id    = McMacMiiTxCfg_t;
    uint32 cmd       = 0;
    uint32 fld_id    = 0;
    uint32 val32     = 0;
    uint32 step      = McMacMiiTxCfg_cfgMcMacMiiTx_1_cfgMcMacTxRsFecEn_f -McMacMiiTxCfg_cfgMcMacMiiTx_0_cfgMcMacTxRsFecEn_f;
    McMacMiiTxCfg_m  mcmac_tx;

    index = DRV_INS(txqm_id, 0);
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mcmac_tx));

    for (factor = 0; factor < SYS_TMM_MAX_MAC_NUM_PER_TXQM; factor ++)
    {
        fld_id = McMacMiiTxCfg_cfgMcMacMiiTx_0_cfgMcMacTxRsFecEn_f + step*factor;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mcmac_tx, txqm_id, 0);

        fld_id = McMacMiiTxCfg_cfgMcMacMiiTx_0_cfgMcMacTxRsFecMode_f + step*factor;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mcmac_tx, txqm_id, 0);

        fld_id = McMacMiiTxCfg_cfgMcMacMiiTx_0_cfgMcMacTxAmInsertEn_f + step*factor;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mcmac_tx, txqm_id, 0);
    }

    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mcmac_tx));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_macpcs_en_cfg(uint8 lchip, uint8 flexe_shim_id, uint8 cs_id, uint8 enable)
{
    uint8 txqm_id = 0;
    SYS_TMM_FLEXE_CS_2_TXQM(cs_id, txqm_id);
    if (enable)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_phyinst_bitmap_init(lchip, cs_id));
        CTC_ERROR_RETURN(_sys_tmm_flexe_pcs_cal_init(lchip, cs_id));
        CTC_ERROR_RETURN(_sys_tmm_flexe_mactx_init(lchip, txqm_id));
        CTC_ERROR_RETURN(_sys_tmm_flexe_mactx_portmap_init(lchip, txqm_id));
        CTC_ERROR_RETURN(_sys_tmm_flexe_macrx_cal_init(lchip, txqm_id));
        CTC_ERROR_RETURN(_sys_tmm_flexe_macrx_chanmap_init(lchip, txqm_id));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_hata_cfg(lchip, txqm_id, SYS_FLEXE_DIR_TX, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_hata_cfg(lchip, txqm_id, SYS_FLEXE_DIR_RX, TRUE));

        CTC_ERROR_RETURN(_sys_tmm_flexe_mac_rsv_cfg(lchip, txqm_id, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_misc_init(lchip, cs_id));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_mac_flexe_en(lchip, txqm_id, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_mac_send_en(lchip, txqm_id, TRUE));
    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_mac_send_en(lchip, txqm_id, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_mac_flexe_en(lchip, txqm_id, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_mac_rsv_cfg(lchip, txqm_id, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_hata_cfg(lchip, txqm_id, SYS_FLEXE_DIR_TX, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_hata_cfg(lchip, txqm_id, SYS_FLEXE_DIR_RX, FALSE));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_subcal_flush_cfg(uint8 lchip, uint8 flexe_shim_id, uint32 ins_id, sys_flexe_dir_t dir, uint32 val32)
{
    uint32          cmd   = 0;
    uint32          index = 0;
    uint32          step  = 0;
    uint32          factor = 0;
    uint32          tbl_id = 0;
    uint32          fld_id = 0;

    TxSubcalFlushInst0_m  flush;

    //SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n ### %s @ %d\n", __FUNCTION__, __LINE__);

    /*************** TxSubcalFlushInst0 start! ****************/
    /* #1, calc index */
    index = DRV_INS(flexe_shim_id, 0);

    /* #2, read HW table */
    step = TxSubcalFlushInst1_t - TxSubcalFlushInst0_t;

    factor = ins_id;
    tbl_id = (SYS_FLEXE_DIR_RX == dir) ? RxSubcalFlushInst0_t : TxSubcalFlushInst0_t;
    tbl_id += step*factor;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &flush));

    /* ##2.2. modify field value */
    /* ###2.2.1. */
    fld_id = TxSubcalFlushInst0_mask_f;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &flush, flexe_shim_id, 0);
    FLEXE_DBG_PRINTF("---- ASIC inst %d, %s flush bitmap %x\n", ins_id, dir?"TX":"RX", val32);

    /* #3, write HW table*/
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &flush));
    /*************** TxInterleaveCfgInst end! ****************/

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_400g_phy_reset(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint32 cmd   = 0;
    uint32 index = 0;
    uint32 val32 = 0;
    CtcFlexeShimReset_m  shim_ctl;
    if (!group_node->phy_cnt)
    {
        return CTC_E_NONE;
    }
    if (CTC_CHIP_SERDES_CDG_R8_MODE != group_node->phy_list[0].pcs_mode)
    {
        return CTC_E_NONE;
    }

    /*CtcFlexeShimReset*/
    cmd = DRV_IOR(CtcFlexeShimReset_t, DRV_ENTRY_FLAG);
    index = DRV_INS(group_node->flexe_shim_id, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &shim_ctl));

    val32 = 1;
    DRV_IOW_FIELD_NZ(lchip, CtcFlexeShimReset_t, CtcFlexeShimReset_resetFlexeShimTx_f,  \
        &val32, &shim_ctl, group_node->flexe_shim_id, 0);
    cmd = DRV_IOW(CtcFlexeShimReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &shim_ctl));

    val32 = 0;
    DRV_IOW_FIELD_NZ(lchip, CtcFlexeShimReset_t, CtcFlexeShimReset_resetFlexeShimTx_f,  \
        &val32, &shim_ctl, group_node->flexe_shim_id, 0);
    cmd = DRV_IOW(CtcFlexeShimReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &shim_ctl));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_pcs_set_flexe_config(uint8 lchip, 
                              uint8 cs_id,
                              uint8 pcs_index,
                              uint32 group_id,
                              ctc_chip_serdes_mode_t mode,
                              ctc_port_fec_type_t fec_type,
                              uint8 enable,
                              uint8 first_bind)
{
    uint8  i      = 0;
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 step   = 0;
    uint32 factor = 0;
    uint32 val32  = 0;
    uint8  pcs_lane_num = 0;
    uint8 logical_serdes_id = 0;
    uint8 base_serdes_id  = 0;
    uint8 physical_serdes_id = 0;
    uint8 physical_lane_id = 0;
    uint32 is_adjust = 0;
    uint8 hss_id = 0;
    uint8 mcu_id = 0;
    uint32 core_freq = 0;
    sys_flexe_group_t* p_group_node           = NULL;
    McPcsX8LanesFlexeCfg_m   pcs_flexe;
    McPcsX8LanesMiscCfg_m    pcs_misc;
    McPcsX8LanesCreditCtl_m  pcs_credit;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    switch (mode)
    {
    case CTC_CHIP_SERDES_LG_R1_MODE:
        pcs_lane_num = 1;
        break;
    case CTC_CHIP_SERDES_LG_MODE:
    case CTC_CHIP_SERDES_CG_R2_MODE:
        pcs_lane_num = 2;
        break;
    case CTC_CHIP_SERDES_CG_MODE:
    case CTC_CHIP_SERDES_CCG_R4_MODE:
        pcs_lane_num = 4;
        break;
    case CTC_CHIP_SERDES_CDG_R8_MODE:
        pcs_lane_num = 8;
        break;
    default:
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] Unsupported PCS mode %d \n", mode);
        return CTC_E_INVALID_PARAM;
    }

    /*************** (I) McPcsX8LanesFlexeCfg start! ****************/
    /* #1, calc index */
    index = DRV_INS(cs_id, 0);

    /* #2, read HW table */
    tbl_id = McPcsX8LanesFlexeCfg_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_flexe));

    /* ##2.1. calc step */
    step = McPcsX8LanesFlexeCfg_cfgFlexeConvert_1_cfgTxRsFecEn_f - McPcsX8LanesFlexeCfg_cfgFlexeConvert_0_cfgTxRsFecEn_f;
    factor = pcs_index;

    /* ##2.2. modify field value */
    /* ###2.2.1. */
    switch (fec_type)
    {
    case CTC_PORT_FEC_TYPE_RS528:
    case CTC_PORT_FEC_TYPE_RS544:
    case CTC_PORT_FEC_TYPE_RS272:
        val32 = 1;
        break;
    default:
        val32 = 0;
        break;
    }

    val32 = enable ? val32 : 0x1;
    for (i = 0; i < pcs_lane_num; i++)
    {
        fld_id = McPcsX8LanesFlexeCfg_cfgFlexeConvert_0_cfgTxRsFecEn_f + step*(factor+i);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_flexe, cs_id, 0);
    }

    fld_id = McPcsX8LanesFlexeCfg_cfgFlexeConvert_0_cfgChanSpeed_f + step*factor;
    switch (mode)
    {
    case CTC_CHIP_SERDES_LG_R1_MODE:
    case CTC_CHIP_SERDES_LG_MODE:
        val32 = 8;
        break;
    case CTC_CHIP_SERDES_CG_R2_MODE:
    case CTC_CHIP_SERDES_CG_MODE:
        val32 = 9;
        break;
    case CTC_CHIP_SERDES_CCG_R4_MODE:
        val32 = 10;
        break;
    case CTC_CHIP_SERDES_CDG_R8_MODE:
        val32 = 11;
        break;
    default:
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] Unsupported PCS mode %d \n", mode);
        return CTC_E_INVALID_PARAM;
    }
    val32 = enable ? val32 : 0x6;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_flexe, cs_id, 0);

    /* ###2.2.1. */
    fld_id = McPcsX8LanesFlexeCfg_cfgFlexeConvert_0_cfgTxDoneBmp_f + step*factor;
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &pcs_flexe);
    for (i = 0; i < pcs_lane_num; i++)
    {
        switch (cs_id)
        {
        case 0:
            logical_serdes_id = 32 + i + pcs_index;
            break;
        case 1:
            logical_serdes_id = 40 + i + pcs_index;
            break;
        case 2:
            logical_serdes_id = 80 + i + pcs_index;
            break;
        case 3:
            logical_serdes_id = 88 + i + pcs_index;
            break;
        }
        CTC_ERROR_RETURN(_sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, logical_serdes_id, &physical_serdes_id));
        physical_lane_id = physical_serdes_id % TMM_MAX_SERDES_NUM_PER_CS;
        val32 |= (1 << physical_lane_id);
    }
    val32 = enable ? val32 : 0x0;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_flexe, cs_id, 0);

    /* ###2.2.1. */
    fld_id = McPcsX8LanesFlexeCfg_cfgFlexeConvert_0_cfgTxAmInsertEn_f + step*factor;
    val32 = enable ? 1 : 0;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_flexe, cs_id, 0);

    fld_id = McPcsX8LanesFlexeCfg_cfgFlexeConvert_0_cfgTxThreshold_f + step*factor;
    if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A))
    {
        val32 = enable ? 32 : 8;
    }
    else
    {
        val32 = enable ? 63 : 8;
    }
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_flexe, cs_id, 0);

    fld_id = McPcsX8LanesFlexeCfg_cfgFlexeConvert_0_cfgFlexeTxBufAFullThrd_f + step*factor;
    val32 = enable ? 0x46 : 0x7f;
    hss_id = ((cs_id / 2) == 0) ? (4 + cs_id % 2) : (10 + cs_id %2);
    SYS_TMM_HSS_ID_TO_MCU_ID(hss_id, mcu_id);
    CTC_ERROR_RETURN(sys_tmm_mcu_read_shared_memory(lchip, mcu_id, GLB_INFO_FLEXE_ADJUST_SWITCH, 0x0, &is_adjust));
    if(is_adjust && enable && (!first_bind))
    {
        val32 = 0x7f;
    }
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_flexe, cs_id, 0);

    /* ###2.2.1. */
    fld_id = McPcsX8LanesFlexeCfg_cfgFlexeConvert_0_cfgTxRsFecMode_f + step*factor;
    /* .... RS FEC mode:
     *   2'b01: RS_FEC_544
     *   2'b10: RS_FEC_528
     *   2'b11: RS_FEC_272
     *   2'b00: Reserved
     */
    switch (fec_type)
    {
    case CTC_PORT_FEC_TYPE_RS528:
        val32 = 2;
        break;
    case CTC_PORT_FEC_TYPE_RS544:
        val32 = 1;
        break;
    case CTC_PORT_FEC_TYPE_RS272:
        val32 = 3;
        break;
    default:
        val32 = 0;
        break;
    }
    val32 = enable ? val32 : 0x1;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_flexe, cs_id, 0);

    /* ###2.2.1. */
    fld_id = McPcsX8LanesFlexeCfg_cfgFlexeConvert_0_cfgTxAmInterval_f + step*factor;

    if (CTC_CHIP_SERDES_LG_MODE == mode)
    {
        if (CTC_PORT_FEC_TYPE_NONE == fec_type)
        {
            val32 = 16382;
        }
        else
        {
            val32 = 20478;
        }
    }
    else if (CTC_CHIP_SERDES_LG_R1_MODE == mode)
    {
        val32 = 20478;
    }
    else if ((CTC_CHIP_SERDES_CG_MODE == mode) || (CTC_CHIP_SERDES_CG_R2_MODE == mode))
    {
        val32 = 16383;
    }
    else if (CTC_CHIP_SERDES_CCG_R4_MODE == mode)
    {
        val32 = 20479;
    }
    else if (CTC_CHIP_SERDES_CDG_R8_MODE == mode)
    {
        val32 = 20479;
    }
    else
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] Unsupported PCS mode %d \n", mode);
        return CTC_E_INVALID_PARAM;
    }
    val32 = enable ? val32 : 0x3fff;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_flexe, cs_id, 0);

    /* #3, write HW table*/
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_flexe));
    /*************** (I) McPcsX8LanesFlexeCfg end! ****************/

    /*************** (II) McPcsX8LanesMiscCfg start! ****************/
    /* #1, calc index */
    index = DRV_INS(cs_id, 0);

    /* #2, read HW table */
    tbl_id = McPcsX8LanesMiscCfg_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_misc));

    /* ##2.1. calc step */

    /* ##2.2. modify field value */

    /* ###2.2.1. */
    fld_id = McPcsX8LanesMiscCfg_cfgMcPcsFlexeMode_f;

    /*when phy in this cs is used by other group, val32 of McPcsX8LanesMiscCfg_cfgMcPcsFlexeMode should be 1.*/
    if (enable)
    {
        val32 = 1;
    }
    else
    {
        val32 = 0;
        SYS_FLEXE_CS_2_BASE_LOGIC_SERDES(cs_id, base_serdes_id);
        /*Tranverse the whole CS*/
        for(i = base_serdes_id; i < base_serdes_id + TMM_MAX_SERDES_NUM_PER_CS; i ++)
        {
            p_group_node = _sys_tmm_flexe_group_lookup_by_serdes(lchip, i);
            if (p_group_node && (group_id != p_group_node->group_id))
            {
                val32 = 1;
                break;
            }
        }
    }
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_misc, cs_id, 0);

    /* #3, write HW table*/
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_misc));
    /*************** (II) McPcsX8LanesMiscCfg end! ****************/

    /*************** (III) McPcsX8LanesCreditCtl start! ****************/

    core_freq = sys_usw_datapath_get_core_clock(lchip, 0);

    /* #1, calc index */
    index = DRV_INS(cs_id, 0);

    /* #2, read HW table */
    tbl_id = McPcsX8LanesCreditCtl_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_credit));

    /* ##2.1. calc step */
    step = McPcsX8LanesCreditCtl_cfgTxCreditThrd_1_cfgTxCreditThrd_f - McPcsX8LanesCreditCtl_cfgTxCreditThrd_0_cfgTxCreditThrd_f;
    factor = pcs_index;

    /* ##2.2. modify field value */

    /* ###2.2.1. */
    fld_id = McPcsX8LanesCreditCtl_cfgTxCreditThrd_0_cfgTxCreditThrd_f + step*factor;
    if (CTC_CHIP_SERDES_LG_MODE == mode)
    {
        val32 = 0x18;
        if (800 == core_freq)
        {
            val32 = 0x24;
        }
    }
    else if (CTC_CHIP_SERDES_LG_R1_MODE == mode)
    {
        val32 = 0x18;
        if ((CTC_PORT_FEC_TYPE_RS272 == fec_type) && (1050 == core_freq))
        {
            val32 = 0x1c;
        }
    }
    else if (CTC_CHIP_SERDES_CG_MODE == mode)
    {
        val32 = 64;
    }
    else if (CTC_CHIP_SERDES_CG_R2_MODE == mode)
    {
        val32 = 48;
    }
    else if (CTC_CHIP_SERDES_CCG_R4_MODE == mode)
    {
        val32 = 108;
    }
    else if (CTC_CHIP_SERDES_CDG_R8_MODE == mode)
    {
        val32 = 192;
    }
    else
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] Unsupported PCS mode %d \n", mode);
        return CTC_E_INVALID_PARAM;
    }
    val32 = enable ? val32 : 0x30;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_credit, cs_id, 0);

    /* #3, write HW table*/
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_credit));

    /*************** (III) McPcsX8LanesCreditCtl end! ****************/

    return CTC_E_NONE;
}

/*
 * enable: Ethernet -> FlexE
 * disable: FlexE -> Ethernet
 */
STATIC int32
_sys_tmm_flexe_set_phy_config(uint8 lchip, sys_flexe_group_t* group_node, uint8 enable, uint8 first_bind)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 cs_id = 0;
    uint8 pcs_lane_bmp[TMM_MAX_CS_NUM_PER_SHIM*2] = {0};  /* id: CS 0/1/2/3, uint8 as 8-lane per CS */

    for (i = 0; i < group_node->phy_cnt; i++)
    {
        SYS_TMM_FLEXE_SERDES_2_CS(group_node->phy_list[i].logical_serdes_base, cs_id);
        SYS_CONDITION_CONTINUE(4 <= cs_id);
        pcs_lane_bmp[cs_id] |= (1<<(group_node->phy_list[i].logical_serdes_base%TMM_MAX_SERDES_NUM_PER_CS));
    }

    for (i = 0; i < TMM_MAX_CS_NUM_PER_SHIM*2; i++)
    {
        SYS_CONDITION_CONTINUE(!pcs_lane_bmp[i]);
        for (j = 0; j < TMM_MAX_SERDES_NUM_PER_CS; j++)
        {
            SYS_CONDITION_CONTINUE(0 == ((pcs_lane_bmp[i]>>j) & 0x1));
            CTC_ERROR_RETURN(_sys_tmm_pcs_set_flexe_config(lchip, i, j, group_node->group_id, group_node->phy_list[0].pcs_mode, \
                                    group_node->phy_list[0].fec_type, enable, first_bind));
            first_bind = FALSE;
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_phyinst_bitmap_en(uint8 lchip, sys_flexe_group_t* group_node, uint8 enable)
{
    uint8  i      = 0; 
    uint8  pcs_id = 0;
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;
    uint8  cs_id  = 0;
    uint8  speed  = 0;
    uint32 bmp[2] = {0};  /* --- CS0/CS2; 1 -- CS1/CS3 */
    McPcsX8LanesMiscCfg_m    pcs_misc;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed);
    /*************** (II) McPcsX8LanesMiscCfg start! ****************/
    tbl_id = McPcsX8LanesMiscCfg_t;
    fld_id = McPcsX8LanesMiscCfg_cfgMcPcsFlexeInstEnBmp_f;
    for (i = 0; i < group_node->phy_cnt; i++)
    {
        SYS_TMM_FLEXE_SERDES_2_CS(group_node->phy_list[i].logical_serdes_base, cs_id);
        pcs_id = group_node->phy_list[i].logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS;

        if (CTC_PORT_SPEED_50G == speed)
        {
            bmp[cs_id%2] |= (1 << pcs_id);
        }
        else if (CTC_PORT_SPEED_100G == speed)
        {
            bmp[cs_id%2] |= ((1 << pcs_id)|(1 << (pcs_id+1)));
        }
        else if (CTC_PORT_SPEED_200G == speed)
        {
            bmp[cs_id%2] |= ((1 << pcs_id)\
                       |(1 << (pcs_id+1))\
                       |(1 << (pcs_id+2))\
                       |(1 << (pcs_id+3)));
        }
        else if (CTC_PORT_SPEED_400G == speed)
        {
            bmp[cs_id%2] |= ((1 << pcs_id)\
                       |(1 << (pcs_id+1))\
                       |(1 << (pcs_id+2))\
                       |(1 << (pcs_id+3))\
                       |(1 << (pcs_id+4))\
                       |(1 << (pcs_id+5))\
                       |(1 << (pcs_id+6))\
                       |(1 << (pcs_id+7)));
        }

    }

    for (i = 0; i < 2; i++)
    {
        SYS_CONDITION_CONTINUE(!bmp[i]);
        cs_id = group_node->flexe_shim_id * 2 + i;

        /* #1, calc index */
        index = DRV_INS(cs_id, 0); 

        /* #2, read HW table */
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_misc));
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &pcs_misc);
        FLEXE_DBG_PRINTF(" { %s @ %d} read val32 = 0x%x\n", __FUNCTION__, __LINE__, val32);
        /* ##2.2. modify field value */
        if (enable)
        {
            val32 |= bmp[i];
        }
        else
        {
            val32 &= ~bmp[i];
        }

        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_misc, cs_id, 0);
        FLEXE_DBG_PRINTF(" { %s @ %d} write val32 = 0x%x\n", __FUNCTION__, __LINE__, val32);
        /* #3, write HW table*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_misc));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_mgr_intr_op_set(uint8 lchip, uint8 flexe_shim_id, uint8 inst_bmp, uint8 intr_type, uint8 op_type)
{
    uint8  i = 0;
    uint8  j = 0;
    uint8  word_no = 0;
    uint8  bit = 0;
    uint8  offset = 0;
    uint32 cmd = 0;
    uint32 tbl_id = 0;
    uint32 val32 = 0;
    ds_t   ds;
    RxIntMaskInst0_m rx_mask;

    if (intr_type >= SYS_FLEXE_MGR_INTR_MAX_TYPE)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] FlexE mgr intr type %d out of range!\n", intr_type);
        return CTC_E_INVALID_PARAM;
    }

    if (SYS_FLEXE_MGR_INTR_C == intr_type)
    {
        for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
        {
            SYS_CONDITION_CONTINUE(0 == (inst_bmp & (1 << i)));
            if (INTR_INDEX_VAL_RESET == op_type)
            {
                /*clear*/
                tbl_id = RxGblClrInst0_t;
                tbl_id += (RxGblClrInst1_t - RxGblClrInst0_t)*i;
                cmd = DRV_IOW(tbl_id, RxGblClrInst0_intClearSC_f);
                val32 = 1;
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, DRV_INS(flexe_shim_id, 0), cmd, &val32));
            }
            else if ((INTR_INDEX_MASK_SET == op_type) || (INTR_INDEX_MASK_RESET == op_type))
            {
                tbl_id = RxIntMaskInst0_t;
                tbl_id += (RxIntMaskInst1_t - RxIntMaskInst0_t)*i;
                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, DRV_INS(flexe_shim_id, 0), cmd, &rx_mask));
                val32 = (INTR_INDEX_MASK_SET == op_type) ? 0 : 1;
                SetRxIntMaskInst0(V, calSwitchEv_f, &rx_mask, val32);
                cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, DRV_INS(flexe_shim_id, 0), cmd, &rx_mask));
            }
        }
    }
    else
    {
        sal_memset(&ds, 0, sizeof(ds_t));
        for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
        {
            SYS_CONDITION_CONTINUE(0 == (inst_bmp & (1 << i)));
            offset = i * SYS_FLEXE_MGR_INTR_NUM;
            for (j = 0; j < SYS_FLEXE_MGR_INTR_NUM; j++)
            {
                if (g_flexe_mgr_intr[offset+j].intr_type == intr_type)
                {
                    word_no = g_flexe_mgr_intr[offset+j].word_no;
                    bit     = g_flexe_mgr_intr[offset+j].bit;
                    ds[word_no] |= (0x1 << bit);
                }
            }
        }
        cmd = DRV_IOW(FlexeMgrInterruptFunc_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, DRV_INS(flexe_shim_id, op_type), cmd, &ds));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_phy_rpf_intr_mask(uint8 lchip, uint8 logical_serdes_id, uint8 mask)
{
    uint8 inst_bmp = 0;
    sys_flexe_group_t *group_node = NULL;

    group_node = _sys_tmm_flexe_group_lookup_by_serdes(lchip, logical_serdes_id);
    if (!group_node)
    {
        return CTC_E_NONE;
    }

    _sys_tmm_flexe_get_inst_bmp_by_serdes(lchip, group_node, logical_serdes_id, &inst_bmp);
    FLEXE_DUMP("\n---  (set_rpf_intr_mask) FlexE shim id = %d, inst_bmp = 0x%02x, will set %s!\n\n", group_node->flexe_shim_id, inst_bmp, (mask ? "MASK" : "UNMASK"));
    if (inst_bmp)
    {
        if (mask)
        {
            /* mask */
            CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_intr_op_set(lchip, group_node->flexe_shim_id, inst_bmp, SYS_FLEXE_MGR_INTR_RPF_FALLING, INTR_INDEX_MASK_SET));
            CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_intr_op_set(lchip, group_node->flexe_shim_id, inst_bmp, SYS_FLEXE_MGR_INTR_RPF_RISING,  INTR_INDEX_MASK_SET));
        }
        else
        {
            /* unmask */
            CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_intr_op_set(lchip, group_node->flexe_shim_id, inst_bmp, SYS_FLEXE_MGR_INTR_RPF_FALLING, INTR_INDEX_MASK_RESET));
            CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_intr_op_set(lchip, group_node->flexe_shim_id, inst_bmp, SYS_FLEXE_MGR_INTR_RPF_RISING,  INTR_INDEX_MASK_RESET));
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_phy_ohlock_intr_mask(uint8 lchip, uint8 logical_serdes_id, uint8 mask)
{
    uint8 inst_bmp = 0;
    sys_flexe_group_t *group_node = NULL;

    group_node = _sys_tmm_flexe_group_lookup_by_serdes(lchip, logical_serdes_id);
    if (!group_node)
    {
        return CTC_E_NONE;
    }

    _sys_tmm_flexe_get_inst_bmp_by_serdes(lchip, group_node, logical_serdes_id, &inst_bmp);
    FLEXE_DUMP("\n---  (set_ohlock_intr_mask) FlexE shim id = %d, inst_bmp = 0x%02x, will set %s!\n\n", group_node->flexe_shim_id, inst_bmp, (mask ? "MASK" : "UNMASK"));
    if (inst_bmp)
    {
        if (mask)
        {
            /* mask */
            CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_intr_op_set(lchip, group_node->flexe_shim_id, inst_bmp, SYS_FLEXE_MGR_INTR_OHLOCK,      INTR_INDEX_MASK_SET));
            CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_intr_op_set(lchip, group_node->flexe_shim_id, inst_bmp, SYS_FLEXE_MGR_INTR_OHLOCKLOS,   INTR_INDEX_MASK_SET));
            CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_intr_op_set(lchip, group_node->flexe_shim_id, inst_bmp, SYS_FLEXE_MGR_INTR_OHMFLOCK,    INTR_INDEX_MASK_SET));
            CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_intr_op_set(lchip, group_node->flexe_shim_id, inst_bmp, SYS_FLEXE_MGR_INTR_OHMFLOCKLOS, INTR_INDEX_MASK_SET));
        }
        else
        {
            /* unmask */
            CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_intr_op_set(lchip, group_node->flexe_shim_id, inst_bmp, SYS_FLEXE_MGR_INTR_OHLOCK,      INTR_INDEX_MASK_RESET));
            CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_intr_op_set(lchip, group_node->flexe_shim_id, inst_bmp, SYS_FLEXE_MGR_INTR_OHLOCKLOS,   INTR_INDEX_MASK_RESET));
            CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_intr_op_set(lchip, group_node->flexe_shim_id, inst_bmp, SYS_FLEXE_MGR_INTR_OHMFLOCK,    INTR_INDEX_MASK_RESET));
            CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_intr_op_set(lchip, group_node->flexe_shim_id, inst_bmp, SYS_FLEXE_MGR_INTR_OHMFLOCKLOS, INTR_INDEX_MASK_RESET));
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_group_pcs_chan_bmp_en(uint8 lchip, uint8 cs_id, uint8 pcs_chan_bmp, sys_flexe_dir_t dir, uint8 enable)
{
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32 = 0;
    McPcsX8LanesResetCtl_m     pcs_reset_ctl;
    McPcsX8LanesMcFecCfg_m     pcs_fec_cfg;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    /*************** (I) memset 0 ****************/
    sal_memset(&pcs_reset_ctl, 0, sizeof(McPcsX8LanesResetCtl_m));

    /*************** (II) common info ****************/
    /*
      +----<-----<------<-------  enable
      |         MacTx  PcsTx
      |     +---->------>-------  disable
      |     |
     \|/   /|\
      |     |
      |     +--- <------<-------  disable
      |         MacRx  PcsRx
      +---->----->------>-------  enable
     */

    if (enable)   /* enable */
    {
        /* #1, calc index */
        index = DRV_INS(cs_id, 0);

        if (SYS_FLEXE_DIR_TX == dir)
        {
            /*************** (VII) McPcsX8LanesMcFecCfg start! ****************/
            /* #2, read HW table */
            tbl_id = McPcsX8LanesMcFecCfg_t;
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_fec_cfg));

            fld_id = McPcsX8LanesMcFecCfg_cfgSoftRstTxMcFec_f;
            val32 = 0;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_fec_cfg, cs_id, 0);

            /* #3, write HW table*/
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_fec_cfg));
            /*************** (VII) McPcsX8LanesMcFecCfg end! ****************/

            /*************** (I) McPcsX8LanesResetCtl start! ****************/
            /* #2, read HW table */
            tbl_id = McPcsX8LanesResetCtl_t;
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_reset_ctl));

            fld_id = McPcsX8LanesResetCtl_cfgTxSoftRstChanBmp_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &pcs_reset_ctl);
            val32 &= ~pcs_chan_bmp ;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_reset_ctl, cs_id, 0);

            /* #3, write HW table*/
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_reset_ctl));
            /*************** (I) McPcsX8LanesResetCtl end! ****************/
            /*************** (I) McPcsX8LanesResetCtl start! ****************/
            /* #2, read HW table */
            tbl_id = McPcsX8LanesResetCtl_t;
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_reset_ctl));

            fld_id = McPcsX8LanesResetCtl_cfgTxSoftRstFlexeChanBmp_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &pcs_reset_ctl);
            val32 &= ~pcs_chan_bmp ;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_reset_ctl, cs_id, 0);

            /* #3, write HW table*/
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_reset_ctl));
            /*************** (I) McPcsX8LanesResetCtl end! ****************/
         }
        else  /* RX */
        {
            /*************** (VII) McPcsX8LanesMcFecCfg start! ****************/
            /* #2, read HW table */
            tbl_id = McPcsX8LanesMcFecCfg_t;
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_fec_cfg));

            fld_id = McPcsX8LanesMcFecCfg_cfgSoftRstRxMcFec_f;
            val32 = 0;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_fec_cfg, cs_id, 0);

            /* #3, write HW table*/
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_fec_cfg));
            /*************** (VII) McPcsX8LanesMcFecCfg end! ****************/

            /*************** (I) McPcsX8LanesResetCtl start! ****************/
            /* #2, read HW table */
            tbl_id = McPcsX8LanesResetCtl_t;
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_reset_ctl));

            fld_id = McPcsX8LanesResetCtl_cfgRxSoftRstChanBmp_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &pcs_reset_ctl);
            val32 &= ~pcs_chan_bmp;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_reset_ctl, cs_id, 0);

            fld_id = McPcsX8LanesResetCtl_cfgRxSoftRstFlexeChanBmp_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &pcs_reset_ctl);
            val32 &= ~pcs_chan_bmp;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_reset_ctl, cs_id, 0);

            /* #3, write HW table*/
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_reset_ctl));
            /*************** (I) McPcsX8LanesResetCtl end! ****************/
        }
    }
    else     /* disable */
    {
        if (SYS_FLEXE_DIR_TX == dir)
        {
            /*************** (I) McPcsX8LanesResetCtl start! ****************/
            /* #1, calc index */
            index = DRV_INS(cs_id, 0);

            /* #2, read HW table */
            tbl_id = McPcsX8LanesResetCtl_t;
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_reset_ctl));

            fld_id = McPcsX8LanesResetCtl_cfgTxSoftRstFlexeChanBmp_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &pcs_reset_ctl);
            val32 |= pcs_chan_bmp ;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_reset_ctl, cs_id, 0);

            /* #3, write HW table*/
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_reset_ctl));
            /*************** (I) McPcsX8LanesResetCtl end! ****************/
            /*************** (I) McPcsX8LanesResetCtl start! ****************/
            /* #2, read HW table */
            tbl_id = McPcsX8LanesResetCtl_t;
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_reset_ctl));

            fld_id = McPcsX8LanesResetCtl_cfgTxSoftRstChanBmp_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &pcs_reset_ctl);
            val32 |= pcs_chan_bmp ;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_reset_ctl, cs_id, 0);

            /* #3, write HW table*/
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_reset_ctl));
            /*************** (I) McPcsX8LanesResetCtl end! ****************/
        }
        else
        {
            /*************** (I) McPcsX8LanesResetCtl start! ****************/
            /* #1, calc index */
            index = DRV_INS(cs_id, 0);

            /* #2, read HW table */
            tbl_id = McPcsX8LanesResetCtl_t;
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_reset_ctl));

            fld_id = McPcsX8LanesResetCtl_cfgRxSoftRstChanBmp_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &pcs_reset_ctl);
            val32 |= pcs_chan_bmp ;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_reset_ctl, cs_id, 0);

            /* #3, write HW table*/
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_reset_ctl));
            /*************** (I) McPcsX8LanesResetCtl end! ****************/
            sal_task_sleep(10);
            /*************** (I) McPcsX8LanesResetCtl start! ****************/
            tbl_id = McPcsX8LanesResetCtl_t;
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_reset_ctl));

            fld_id = McPcsX8LanesResetCtl_cfgRxSoftRstFlexeChanBmp_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &pcs_reset_ctl);
            val32 |= pcs_chan_bmp ;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_reset_ctl, cs_id, 0);

            /* #3, write HW table*/
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_reset_ctl));
            /*************** (I) McPcsX8LanesResetCtl end! ****************/
        }
    }

    return CTC_E_NONE;
}

int32
_sys_tmm_flexe_group_adjust_afull_thrd_get_cmd_code(uint8 lchip, 
                                                      uint8 phy_mode,
                                                      uint8 fec_type, 
                                                      uint8 cs_id, 
                                                      uint8 pcs_chan_bmp, 
                                                      uint8 type, 
                                                      uint32 *cmd_code)
{
    uint8 hss_id              = 0;
    uint8 mcu_id              = 0;
    uint8 enable              = TRUE;
    uint8 work_mode           = 0;
    uint8 lane_id             = 0;
    uint8 lane_num            = 0;
    uint8 physical_serdes_id  = 0;
    uint8 logical_serdes_id   = 0;
    uint8 phy_pcs_chan_bmp    = 0;
    uint32 is_adjust          = 0;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "cs_id is %d, and pcs_chan_bmp is %d\n", cs_id, pcs_chan_bmp);

    hss_id = ((cs_id / 2) == 0) ? (4 + cs_id % 2) : (10 + cs_id % 2);
    SYS_TMM_HSS_ID_TO_MCU_ID(hss_id, mcu_id);

    if((fec_type == CTC_PORT_FEC_TYPE_RS544) || (fec_type == CTC_PORT_FEC_TYPE_RS272))
    {
        work_mode = SYS_MCU_FLEXE_CMD_WK_MODE_RS544;
    }
    else
    {
        work_mode = SYS_MCU_FLEXE_CMD_WK_MODE_NONE_RS528;
    }

    CTC_ERROR_RETURN(sys_tmm_mcu_read_shared_memory(lchip, mcu_id, GLB_INFO_FLEXE_ADJUST_SWITCH, 0x0, &is_adjust));

    switch(type)
    {
        /*bind phy*/
        case SYS_TMM_FLEXE_ADJ_AFULL_THRD_TYPE_BIND:
            enable = is_adjust ? SYS_MCU_FLEXE_CMD_ENABLE_RD_ADJ : SYS_MCU_FLEXE_CMD_ENABLE_ONLY_RD;
            break;
        /*unbind phy*/
        case SYS_TMM_FLEXE_ADJ_AFULL_THRD_TYPE_UNBIND:
            enable = SYS_MCU_FLEXE_CMD_ENABLE_RD_STATS;
            break;
        default : 
            break;
    }

    SYS_TMM_GET_LANE_NUM_BY_MODE(phy_mode, lane_num);
    for(lane_id = 0; lane_id < TMM_MAX_SERDES_NUM_PER_CS; lane_id ++)
    {
        SYS_CONDITION_CONTINUE(0 == ((pcs_chan_bmp >> lane_id) & 0x1));
        for(logical_serdes_id = hss_id * TMM_MAX_SERDES_NUM_PER_CS + lane_id; \
             logical_serdes_id < hss_id * TMM_MAX_SERDES_NUM_PER_CS + lane_id + lane_num; logical_serdes_id++)
        {
            _sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, logical_serdes_id, &physical_serdes_id);
            SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == physical_serdes_id), CTC_E_INVALID_PARAM);

            phy_pcs_chan_bmp |= (0x1 << (physical_serdes_id % TMM_MAX_SERDES_NUM_PER_CS));
        }
    }

    /* cmd_code 
    * [31, 24] : phy_pcs_chan_bmp, 
    * [23, 16] : pcs_chan_bmp
    * [15, 8] : work_mode
    * [7, 4] : cs_id
    * [3, 0] : enable
    */
    *cmd_code |= (enable << 0);
    *cmd_code |= (cs_id << 4);
    *cmd_code |= (work_mode << 1*8);
    *cmd_code |= (pcs_chan_bmp << 2*8);
    *cmd_code |= (phy_pcs_chan_bmp << 3*8);

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "    %-12s = 0x%x\n", "mcu_id", mcu_id);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "    %-12s = 0x%x\n", "cmd_code", *cmd_code);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "    %-12s = 0x%x\n", "enable", enable);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "    %-12s = 0x%x\n", "work_mode", work_mode);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "    %-12s = 0x%x\n", "pcs_chan_bmp", pcs_chan_bmp);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "    %-12s = 0x%x\n", "phy_pcs_chan_bmp", phy_pcs_chan_bmp);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "    %-12s = 0x%x\n", "cs_id", cs_id);

    return CTC_E_NONE;
}

int32
_sys_tmm_flexe_group_adjust_afull_thrd_unbind_proc(uint8 lchip, uint8 cs_id, uint8 pcs_chan_bmp, uint8 phy_mode)
{
    uint8 lane_id      = 0;
    uint8 hss_id       = 0;
    uint8 mcu_id       = 0;
    uint32 index       = 0;
    uint32 cmd         = 0;
    uint32 fld_id      = 0;
    uint32 step        = 0;
    uint32 cmd_ret     = 0;
    McPcsX8LanesFlexeCfg_m   pcs_flexe;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "cs_id is %d, and pcs_chan_bmp is %d\n", cs_id, pcs_chan_bmp);
    FLEXE_DUMP("\n Enter [FlexE] %s @ %d, cs_id is %d, pcs_chan_bmp is 0x%x, phy_mode is %d\n", __FUNCTION__, __LINE__, \
                                                                                        cs_id, pcs_chan_bmp, phy_mode);

    hss_id = ((cs_id / 2) == 0) ? (4 + cs_id % 2) : (10 + cs_id % 2);
    SYS_TMM_HSS_ID_TO_MCU_ID(hss_id, mcu_id);

    CTC_ERROR_RETURN(sys_tmm_mcu_read_shared_memory(lchip, mcu_id, GLB_INFO_FLEXE_CMD_RESULT, 0x0, &cmd_ret));
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "    %-12s = 0x%x\n", "cmd_ret", cmd_ret);
    FLEXE_DUMP("        %-12s = 0x%x\n", "cmd_ret", cmd_ret);

    /* get cfgFlexeTxBufAFullThrd value*/
    if((CTC_CHIP_SERDES_LG_MODE == phy_mode) || (CTC_CHIP_SERDES_LG_R1_MODE == phy_mode))
    {
        cmd_ret += 24;
    }
    else
    {
        cmd_ret += 16;
    }

    FLEXE_DUMP("        new TxBufAFullThrd value = 0x%x\n", cmd_ret);

    /* read McPcsX8LanesFlexeCfg entry*/
    index = DRV_INS(cs_id, 0);
    cmd = DRV_IOR(McPcsX8LanesFlexeCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_flexe));

    /* modify cfgFlexeTxBufAFullThrd field value*/
    step = McPcsX8LanesFlexeCfg_cfgFlexeConvert_1_cfgFlexeTxBufAFullThrd_f - McPcsX8LanesFlexeCfg_cfgFlexeConvert_0_cfgFlexeTxBufAFullThrd_f;
    for(lane_id = 0; lane_id < TMM_MAX_SERDES_NUM_PER_CS; lane_id ++)
    {
        SYS_CONDITION_CONTINUE(0 == ((pcs_chan_bmp >> lane_id) & 0x1));
        fld_id = McPcsX8LanesFlexeCfg_cfgFlexeConvert_0_cfgFlexeTxBufAFullThrd_f + step*lane_id;
        DRV_IOW_FIELD_NZ(lchip, McPcsX8LanesFlexeCfg_t, fld_id, &cmd_ret, &pcs_flexe, cs_id, 0);
        FLEXE_DUMP("        cs @ %d, pcs chan @ %d, new TxBufAFullThrd value = 0x%x\n", cs_id, lane_id, cmd_ret);
    }

    /* write McPcsX8LanesFlexeCfg entry*/
    cmd = DRV_IOW(McPcsX8LanesFlexeCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_flexe));

    return CTC_E_NONE;
}

int32
_sys_tmm_flexe_group_adjust_afull_thrd(uint8 lchip, sys_flexe_group_t* p_group_node, uint8 cs_id, uint8 pcs_chan_bmp, uint8 type)
{
    uint8 hss_id       = 0;
    uint8 mcu_id       = 0;
    uint8 phy_mode     = 0;
    uint8 fec_type     = 0;
    uint32 cmd_code    = 0;
    uint32 cmd_status  = 0;
    uint32 timeout     = 2500;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "cs_id is %d, and pcs_chan_bmp is %d\n", cs_id, pcs_chan_bmp);
    FLEXE_DUMP("\n Enter [FlexE] %s @ %d, group is %d, cs_id is %d, pcs_chan_bmp is 0x%x, type is %d\n", __FUNCTION__, __LINE__, \
                                                                      p_group_node->group_id, cs_id, pcs_chan_bmp, type);

    hss_id = ((cs_id / 2) == 0) ? (4 + cs_id % 2) : (10 + cs_id % 2);
    SYS_TMM_HSS_ID_TO_MCU_ID(hss_id, mcu_id);

    /*step0 : get phy_mode & fec_type*/
    phy_mode = p_group_node->phy_list[0].pcs_mode;
    fec_type = p_group_node->phy_list[0].fec_type;
    FLEXE_DUMP("        phy_mode = %d, fec_type = %d\n", phy_mode, fec_type);

    /*step1 : get cmd*/
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_adjust_afull_thrd_get_cmd_code(lchip, phy_mode, fec_type, cs_id, pcs_chan_bmp, type, &cmd_code));
    FLEXE_DUMP("        cmd_code = 0x%x\n", cmd_code);

    /*step2 : clear reg of cmd info */
    CTC_ERROR_RETURN(sys_tmm_mcu_write_shared_memory(lchip,      mcu_id, GLB_INFO_FLEXE_CMD_RESULT, 0x0, 0x0));
    CTC_ERROR_RETURN(sys_tmm_mcu_write_shared_memory(lchip,      mcu_id, GLB_INFO_FLEXE_CMD_STATUS, 0x0, 0x0));

    /*step3 : send cmd code to mcu, let mcu read buffer depth*/
    CTC_ERROR_RETURN(sys_tmm_mcu_write_shared_memory(lchip,      mcu_id, GLB_INFO_FLEXE_CMD_CODE, 0x0, cmd_code));

    sal_task_sleep(10);

    /*step4 : wait mcu execute complete */
    while(--timeout)
    {
        sal_task_sleep(2);
        CTC_ERROR_RETURN(sys_tmm_mcu_read_shared_memory(lchip, mcu_id, GLB_INFO_FLEXE_CMD_STATUS, 0x0, &cmd_status));
        FLEXE_DUMP("            timeout = %d, cmd_status = 0x%x\n", timeout, cmd_status);

        if(SYS_MCU_FLEXE_CMD_STATUS_DOING == cmd_status)
        {
            FLEXE_DUMP("        SYS_MCU_FLEXE_CMD_STATUS_DOING\n");
            continue;
        }
        else if(SYS_MCU_FLEXE_CMD_STATUS_DONE == cmd_status)
        {
            FLEXE_DUMP("        SYS_MCU_FLEXE_CMD_STATUS_DONE\n");
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "    %-12s = 0x%x\n", "cmd_status", cmd_status);

            if(SYS_TMM_FLEXE_ADJ_AFULL_THRD_TYPE_UNBIND == type)
            {
                FLEXE_DUMP("        unbind_proc\n");
                CTC_ERROR_RETURN(_sys_tmm_flexe_group_adjust_afull_thrd_unbind_proc(lchip, cs_id, pcs_chan_bmp, phy_mode));
            }

            return CTC_E_NONE;
        }
        else
        {
            FLEXE_DUMP("        SYS_MCU_FLEXE_CMD_STATUS_TIME_OUT or SYS_MCU_FLEXE_CMD_STATUS_FAIL\n");
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "    %-12s = 0x%x\n", "cmd_status", cmd_status);
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "    TimeOut %-12s = 0x%x\n", "cmd_status", cmd_status);
            return CTC_E_NOT_READY;
        }
    }

    CTC_ERROR_RETURN(sys_tmm_mcu_read_shared_memory(lchip, mcu_id, GLB_INFO_FLEXE_CMD_STATUS, 0x0, &cmd_status));
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "    TimeOut %-12s = 0x%x\n", "cmd_status", cmd_status);
    FLEXE_DUMP("            timeout = %d, cmd_status = 0x%x\n", timeout, cmd_status);
    CTC_ERROR_RETURN(sys_tmm_mcu_read_shared_memory(lchip, mcu_id, 0x9c, 0x0, &cmd_status));
    FLEXE_DUMP("            timeout = %d, MCU Code = 0x%x\n", timeout, cmd_status);

    return CTC_E_NOT_READY;
}

STATIC int32
_sys_tmm_flexe_unbind_phylist_adjust_afull(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint8 i                              = 0;
    uint8 j                              = 0;
    uint8 flag                           = FALSE;
    uint8 cs_id                          = 0;
    uint8 pcs_idx                        = 0;
    uint8 base_serdes_id                 = 0;
    uint8 pcs_chan_bmp                   = 0;
    uint8 exist_other_phy                = FALSE;
    uint8 exist_50G_phy                  = FALSE;
    uint8 is_basic_phy                   = FALSE;
    uint32 index                         = 0;
    uint32 cmd                           = 0;
    uint32 fld_id                        = 0;
    uint32 step                          = 0;
    uint32 val32                         = 0;
    uint8  phy_speed                     = 0;
    uint8  tmp_phy_speed                 = 0;
    sys_flexe_group_t* p_tmp_group_node  = NULL;
    sys_flexe_group_t* p_group_node_bak  = NULL;

    FLEXE_DUMP("\n Enter [FlexE] %s @ %d, group is %d\n", __FUNCTION__, __LINE__, group_node->group_id);

    /* step1 : judgement phy in group_node whether is a basic phy*/
    for (i = 0; i < group_node->phy_cnt; i++)
    {
        SYS_TMM_GET_RLMCS(group_node->phy_list[i].logical_serdes_base, cs_id);
        pcs_idx = group_node->phy_list[i].logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS;

        index = DRV_INS(cs_id, 0);
        step = McPcsX8LanesFlexeCfg_cfgFlexeConvert_1_cfgFlexeTxBufAFullThrd_f - McPcsX8LanesFlexeCfg_cfgFlexeConvert_0_cfgFlexeTxBufAFullThrd_f;
        fld_id = McPcsX8LanesFlexeCfg_cfgFlexeConvert_0_cfgFlexeTxBufAFullThrd_f + step*pcs_idx;

        cmd = DRV_IOR(McPcsX8LanesFlexeCfg_t, fld_id);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &val32));

        FLEXE_DUMP("        cs_id %d, pcs_idx %d, fld_id %d, TxBufAFullThrd value 0x%x\n", cs_id, pcs_idx, fld_id, val32);

        if(0x7f != val32)
        {
            is_basic_phy = TRUE;
            FLEXE_DUMP("        logical serdes %d is basic phy\n", group_node->phy_list[i].logical_serdes_base);
            break;
        }

    }

    /* if it isn't a basic phy, and return */
    if (!is_basic_phy)
    {
        FLEXE_DUMP("        group %d don't exist basic phy.\n", group_node->group_id);
        return CTC_E_NONE;
    }

    /* step2 : judgement phy in other group of same shim whether if exist */
    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &phy_speed);
    base_serdes_id = (group_node->flexe_shim_id == 0) ? 32 : 80;
    for (i = base_serdes_id; i < base_serdes_id + TMM_MAX_SERDES_NUM_PER_CS*2; i ++)
    {
        p_tmp_group_node = _sys_tmm_flexe_group_lookup_by_serdes(lchip, i);
        SYS_CONDITION_CONTINUE(!p_tmp_group_node);
        SYS_CONDITION_CONTINUE(p_tmp_group_node->group_id == group_node->group_id);
        if(FALSE == flag)
        {
            p_group_node_bak = p_tmp_group_node;
            flag = TRUE;
            FLEXE_DUMP("        Find First Other group @ %d\n", p_tmp_group_node->group_id);
        }

        exist_other_phy = TRUE;

        _sys_tmm_flexe_get_group_phy_speed(lchip, p_tmp_group_node, &tmp_phy_speed);
        for (j = 0; j < p_tmp_group_node->phy_cnt; j ++)
        {
            if (CTC_PORT_SPEED_50G == tmp_phy_speed)
            {
                exist_50G_phy = TRUE;
                FLEXE_DUMP("        Find Other group @ %d have 50G PHY\n", p_tmp_group_node->group_id);
                break;
            }
        }

        if (exist_50G_phy)
        {
            break;
        }
    }

    /* if don't exist other phy , and return */
    if (!exist_other_phy)
    {
        FLEXE_DUMP("        Don't exist ohter phy.\n");
        return CTC_E_NONE;
    }
    else
    {
        if(!exist_50G_phy)
        {
            p_tmp_group_node = p_group_node_bak;
        }
    }

    /* step3 : find other phy in same shim as a new basic phy */
    for (i = 0; i < p_tmp_group_node->phy_cnt; i++)
    {
        _sys_tmm_flexe_get_group_phy_speed(lchip, p_tmp_group_node, &tmp_phy_speed);
        SYS_CONDITION_CONTINUE(exist_50G_phy && (CTC_PORT_SPEED_50G != tmp_phy_speed));
        SYS_TMM_GET_RLMCS(p_tmp_group_node->phy_list[i].logical_serdes_base, cs_id);
        pcs_chan_bmp |= (1<<(p_tmp_group_node->phy_list[i].logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS));

        FLEXE_DUMP("        Find group @ %d, PHY @ %d as a new basic phy\n", p_tmp_group_node->group_id, \
            p_tmp_group_node->phy_list[i].logical_serdes_base);
        break;
    }

    CTC_ERROR_RETURN(_sys_tmm_flexe_group_adjust_afull_thrd(lchip, p_tmp_group_node, cs_id, pcs_chan_bmp, \
                                                                           SYS_TMM_FLEXE_ADJ_AFULL_THRD_TYPE_UNBIND));

    /* step4 : change TxBufAFullThrd value of old basic phy to 0x7f*/
    val32 = 0x7f;
    cmd = DRV_IOW(McPcsX8LanesFlexeCfg_t, fld_id);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &val32));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_reset_shim(uint8 lchip, uint8 flexe_shim_id)
{
    uint8 i = 0;
    uint8 base_serdes_id = 0;
    uint8 reset_flag = 1;
    uint32 cmd = 0;
    uint32 index = 0;
    uint32 tmp_val32 = 0;
    sys_flexe_group_t *p_tmp_group_node = NULL;
    CtcFlexeShimReset_m shim_reset;

    base_serdes_id = (flexe_shim_id == 0) ? 32 : 80;
    for (i = base_serdes_id; i < base_serdes_id + TMM_MAX_SERDES_NUM_PER_CS*2; i ++)
    {
        p_tmp_group_node = _sys_tmm_flexe_group_lookup_by_serdes(lchip, i);
        if (p_tmp_group_node)
        {
            reset_flag = 0;
            break;
        }
    }

    if (reset_flag)  /* No group exists in this DP */
    {
        FLEXE_DUMP("-------- FlexE shim %d trigger CtcFlexeShimReset_resetFlexeShim_f!\n", flexe_shim_id);
        index = DRV_INS(flexe_shim_id, 0);
        cmd = DRV_IOR(CtcFlexeShimReset_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &shim_reset));
        tmp_val32 = 1;
        DRV_IOW_FIELD_NZ(lchip, CtcFlexeShimReset_t, CtcFlexeShimReset_resetFlexeShim_f, &tmp_val32, &shim_reset, flexe_shim_id, 0);
        cmd = DRV_IOW(CtcFlexeShimReset_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &shim_reset));

        tmp_val32 = 0;
        DRV_IOW_FIELD_NZ(lchip, CtcFlexeShimReset_t, CtcFlexeShimReset_resetFlexeShim_f, &tmp_val32, &shim_reset, flexe_shim_id, 0);
        cmd = DRV_IOW(CtcFlexeShimReset_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &shim_reset));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_phy_en(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, uint8 enable, uint8 first_bind)
{
    uint8 i                    = 0;
    uint8 j                    = 0;
    uint8 cs_id                = 0;
    uint8 phy_lane_num         = 0;
    uint8 physical_serdes_id   = 0;
    uint8 pcs_chan_bmp[4]      = {0};  /* id: CS 0/1/2/3 */

    for (i = 0; i < group_node->phy_cnt; i++)
    {
        SYS_TMM_FLEXE_SERDES_2_CS(group_node->phy_list[i].logical_serdes_base, cs_id);
        SYS_CONDITION_CONTINUE(4 <= cs_id);
        pcs_chan_bmp[cs_id] |= (1<<(group_node->phy_list[i].logical_serdes_base%TMM_MAX_SERDES_NUM_PER_CS));
    }

    _sys_tmm_flexe_get_phy_lane_num(lchip, group_node->phy_list[0].logical_serdes_base, &phy_lane_num);
    if(!enable && (SYS_FLEXE_DIR_TX == dir))
    {
        for (i = 0; i < group_node->phy_cnt; i++)
        {
            for (j = 0; j < phy_lane_num; j++)
            {
                _sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, \
                    (group_node->phy_list[i].logical_serdes_base+j), &physical_serdes_id);
                CTC_ERROR_RETURN(sys_tmm_serdes_set_tx_en(lchip, physical_serdes_id, FALSE));
            }
        }
    }

    if (!enable && (SYS_FLEXE_DIR_RX == dir))
    {
        for (i = 0; i < group_node->phy_cnt; i++)
        {
            //-CTC_ERROR_RETURN(_sys_tmm_flexe_set_crcac_intr_mask(lchip, group_node->phy_list[i].logical_serdes_base, TRUE));
            CTC_ERROR_RETURN(_sys_tmm_flexe_set_phy_ohlock_intr_mask(lchip, group_node->phy_list[i].logical_serdes_base, TRUE));
        }
    }

    for (i = 0; i < 4; i++)
    {
        if (pcs_chan_bmp[i])
        {
            CTC_ERROR_RETURN(_sys_tmm_group_pcs_chan_bmp_en(lchip, i, pcs_chan_bmp[i], dir, enable));

            if(enable && (!first_bind) && (SYS_FLEXE_DIR_TX == dir))
            {
                CTC_ERROR_RETURN(_sys_tmm_flexe_group_adjust_afull_thrd(lchip, group_node, i, pcs_chan_bmp[i], \
                                                                            SYS_TMM_FLEXE_ADJ_AFULL_THRD_TYPE_BIND));
            }
        }
    }

    if(enable && (SYS_FLEXE_DIR_TX == dir))
    {
        for (i = 0; i < group_node->phy_cnt; i++)
        {
            for (j = 0; j < phy_lane_num; j++)
            {
                _sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, \
                    (group_node->phy_list[i].logical_serdes_base+j), &physical_serdes_id);
                CTC_ERROR_RETURN(sys_tmm_serdes_set_tx_en(lchip, physical_serdes_id, TRUE));
            }
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_phyinst_convert_txenable(uint8 lchip, sys_flexe_group_t* group_node, uint8 enable)
{
    uint8  i      = 0; 
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 step   = 0;
    uint32 factor = 0;
    uint32 val32  = 0;
    uint8  cs_id  = 0;
    McPcsX8LanesFlexeCfg_m    pcs_flexe_en;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /*************** (VII) McPcsX8LanesFlexeCfg start! ****************/
    tbl_id = McPcsX8LanesFlexeCfg_t;
    for (i = 0; i < group_node->phy_cnt; i++)
    {
        /* #1, calc index */
        SYS_TMM_FLEXE_SERDES_2_CS(group_node->phy_list[i].logical_serdes_base, cs_id);
        index = DRV_INS(cs_id, 0);

        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_flexe_en));

        val32 = enable ? 1 : 0;

        /* ##2.2. modify field value */
        step = McPcsX8LanesFlexeCfg_cfgFlexeConvert_1_cfgTxEnable_f - McPcsX8LanesFlexeCfg_cfgFlexeConvert_0_cfgTxEnable_f;
        factor = group_node->phy_list[i].logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS;
        fld_id = McPcsX8LanesFlexeCfg_cfgFlexeConvert_0_cfgTxEnable_f + step*factor;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_flexe_en, cs_id, 0);

        /* #3, write HW table*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_flexe_en));
    }

    /*************** (VII) McPcsX8LanesFlexeCfg end! ****************/

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_group_linesel_cfg(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, uint8 enable)
{
    uint8  i                           = 0;
    uint8  cs_id                       = 0;
    uint32 cmd                         = 0;
    uint8  inst_num                    = 0;
    uint32 index                       = 0;
    uint32 step                        = 0;
    uint32 factor                      = 0;
    uint32 tbl_id                      = 0;
    uint32 fld_id                      = 0;
    uint32 val32                       = 0;
    uint8  phy_speed                   = 0;
    uint32 tx_buf_id[SYS_FLEXE_MAX_INST_CNT] = {0};
    uint32 inst_list[SYS_FLEXE_MAX_INST_CNT] = {0};
    uint32 cs_flag[SYS_FLEXE_MAX_INST_CNT]   = {0};
    sys_flexe_phy_t *p_phy         = NULL;
    FlexeLineSelCfg_m   line_sel;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &phy_speed);
    /********************************************************************************************
     -- FlexeLineSelCfg.flexeLineMux_0_cfgFlexeRxSelBmp
                       .flexeLineMux_0_cfgFlexeTxSelBmp 
    *********************************************************************************************/

    /*************** FlexeLineSelCfg start! ****************/
    /* #1, calc index */
    index = DRV_INS(group_node->flexe_shim_id, 0);

    /* #2, read HW table */
    tbl_id = FlexeLineSelCfg_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &line_sel));

    /* ##2.2. modify field value */
    /* ###2.2.1. */
    step = FlexeLineSelCfg_flexeLineMux_1_cfgFlexeRxSelBmp_f - FlexeLineSelCfg_flexeLineMux_0_cfgFlexeRxSelBmp_f;

    for (i = 0; i < group_node->phy_cnt; i++)
    {
        p_phy = &group_node->phy_list[i];
        SYS_TMM_FLEXE_SERDES_2_CS(p_phy->logical_serdes_base, cs_id);
        if (CTC_PORT_SPEED_50G == phy_speed)
        {
            inst_list[inst_num] = p_phy->inst_base;
            tx_buf_id[inst_num] = p_phy->logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS;
            cs_flag[inst_num]   = cs_id;
            inst_num++;
        }
        else if (CTC_PORT_SPEED_100G == phy_speed)
        {
            inst_list[inst_num]   = p_phy->inst_base;
            inst_list[inst_num+1] = p_phy->inst_base+1;
            tx_buf_id[inst_num]   = p_phy->logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS;
            tx_buf_id[inst_num+1] = p_phy->logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS+1;
            cs_flag[inst_num]     = cs_id;
            cs_flag[inst_num+1]   = cs_id;
            inst_num += 2;
        }
        else if (CTC_PORT_SPEED_200G == phy_speed)
        {
            inst_list[inst_num]   = p_phy->inst_base;
            inst_list[inst_num+1] = p_phy->inst_base+1;
            inst_list[inst_num+2] = p_phy->inst_base+2;
            inst_list[inst_num+3] = p_phy->inst_base+3;
            tx_buf_id[inst_num]   = p_phy->logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS;
            tx_buf_id[inst_num+1] = p_phy->logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS+1;
            tx_buf_id[inst_num+2] = p_phy->logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS+2;
            tx_buf_id[inst_num+3] = p_phy->logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS+3;
            cs_flag[inst_num]     = cs_id;
            cs_flag[inst_num+1]   = cs_id;
            cs_flag[inst_num+2]   = cs_id;
            cs_flag[inst_num+3]   = cs_id;
            inst_num += 4;
        }
        else if (CTC_PORT_SPEED_400G == phy_speed)
        {
            inst_list[inst_num]   = p_phy->inst_base;
            inst_list[inst_num+1] = p_phy->inst_base+1;
            inst_list[inst_num+2] = p_phy->inst_base+2;
            inst_list[inst_num+3] = p_phy->inst_base+3;
            inst_list[inst_num+4] = p_phy->inst_base+4;
            inst_list[inst_num+5] = p_phy->inst_base+5;
            inst_list[inst_num+6] = p_phy->inst_base+6;
            inst_list[inst_num+7] = p_phy->inst_base+7;
            tx_buf_id[inst_num]   = p_phy->logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS;
            tx_buf_id[inst_num+1] = p_phy->logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS+1;
            tx_buf_id[inst_num+2] = p_phy->logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS+2;
            tx_buf_id[inst_num+3] = p_phy->logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS+3;
            tx_buf_id[inst_num+4] = p_phy->logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS+4;
            tx_buf_id[inst_num+5] = p_phy->logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS+5;
            tx_buf_id[inst_num+6] = p_phy->logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS+6;
            tx_buf_id[inst_num+7] = p_phy->logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS+7;
            cs_flag[inst_num]     = cs_id;
            cs_flag[inst_num+1]   = cs_id;
            cs_flag[inst_num+2]   = cs_id;
            cs_flag[inst_num+3]   = cs_id;
            cs_flag[inst_num+4]   = cs_id;
            cs_flag[inst_num+5]   = cs_id;
            cs_flag[inst_num+6]   = cs_id;
            cs_flag[inst_num+7]   = cs_id;
            inst_num += 8;
        }
    }

    for (i = 0; i < inst_num; i++)
    {
        factor = inst_list[i];
        if(enable)
        {
            val32 = 1 << tx_buf_id[i];
            if (cs_flag[i] % 2) /* CS1/CS3 */
            {
                val32 |= (1 << TMM_MAX_SERDES_NUM_PER_CS);
            }
        }
        else
        {
            val32 &= ~(1 << tx_buf_id[i]);
            if (cs_flag[i] % 2) /* CS1/CS3 */
            {
                val32 &= ~ (1 << TMM_MAX_SERDES_NUM_PER_CS);
            }
        }
        fld_id = ((SYS_FLEXE_DIR_RX == dir) ? \
            FlexeLineSelCfg_flexeLineMux_0_cfgFlexeRxSelBmp_f : \
            FlexeLineSelCfg_flexeLineMux_0_cfgFlexeTxSelBmp_f);
        fld_id += step*factor;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &line_sel, group_node->flexe_shim_id, 0);
    }

    /* #3, write HW table*/
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &line_sel));
    /*************** FlexeLineMuxCfg end! ****************/

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_group_en(uint8 lchip, sys_flexe_group_t* group_node, uint8 enable, uint8 first_bind)
{
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    if (!enable)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_phyinst_bitmap_en(lchip, group_node, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_phy_en(lchip, group_node, SYS_FLEXE_DIR_TX, FALSE, first_bind));
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_phy_en(lchip, group_node, SYS_FLEXE_DIR_RX, FALSE, first_bind));
        CTC_ERROR_RETURN(_sys_tmm_flexe_phyinst_convert_txenable(lchip, group_node, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_group_linesel_cfg(lchip, group_node, SYS_FLEXE_DIR_RX, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_group_linesel_cfg(lchip, group_node, SYS_FLEXE_DIR_TX, FALSE));
    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_group_linesel_cfg(lchip, group_node, SYS_FLEXE_DIR_RX, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_group_linesel_cfg(lchip, group_node, SYS_FLEXE_DIR_TX, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_phyinst_convert_txenable(lchip, group_node, TRUE));

        /* PCS chan bmp in one group must set to 1 simutaneously */
        CTC_ERROR_RETURN(_sys_tmm_flexe_phyinst_bitmap_en(lchip, group_node, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_phy_en(lchip, group_node, SYS_FLEXE_DIR_RX, TRUE, first_bind));
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_phy_en(lchip, group_node, SYS_FLEXE_DIR_TX, TRUE, first_bind));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_mgr_cfg(uint8 lchip, sys_flexe_group_t* group_node, uint8 enable)
{
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    _sys_tmm_flexe_mgr_ts_cfg(lchip, group_node, enable);
    _sys_tmm_flexe_mgr_oh_cfg(lchip, group_node, enable);
    _sys_tmm_flexe_mgr_rxmac_cfg(lchip, group_node, enable);

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_soc2p1(uint8 lchip, sys_flexe_group_t* group_node, uint8 enable)
{
    uint32          cmd   = 0;
    uint32          index = 0;
    uint32          tbl_id = 0;
    uint32          fld_id = 0;
    uint32          val32  = 0;
    uint32          inst_id  = 0;
    uint8           i = 0, j = 0;
    uint8           phy_speed = 0;
    uint8           phy_inst_cnt = 0;
    sys_flexe_phy_t* p_phy = NULL;
    SocCfgFlexe2p1_m    soc2p1_bmp;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &phy_speed);
    phy_inst_cnt = SYS_TMM_FLEXE_PHY_2_INST_CNT(phy_speed);

    /*************** SocCfgFlexe2p1 start! ****************/
    /* #1, calc index */
    index = DRV_INS(group_node->flexe_shim_id, 0);

    tbl_id = SocCfgFlexe2p1_t;
    fld_id = SocCfgFlexe2p1_en_f;
    /* #2, read HW table */
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &soc2p1_bmp));
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &soc2p1_bmp);

    for (i = 0; i < group_node->phy_cnt;i++)
    {
        p_phy = &group_node->phy_list[i];
        for (j = 0; j < phy_inst_cnt; j++)
        {
            inst_id = p_phy->inst_base+j;
            if (enable)
            {
                if (CTC_PORT_SPEED_50G == phy_speed)
                {
                    val32 |= (1 << (inst_id/2));
                }
                else
                {
                    val32 &= ~(1 << (inst_id/2));
                }
            }
            else
            {
                val32 |= (1 << (inst_id/2));
            }
        }
    }
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &soc2p1_bmp, group_node->flexe_shim_id, 0);
    /* #3, write HW table*/
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &soc2p1_bmp));

    /*************** TxCtlInst0 end! ****************/

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_mcu_padding_cfg(uint8 lchip, uint8 flexe_shim_id, uint8 inst_bmp)
{
    uint8  mcu_id              = 0;
    int32  ret                 = 0;
    uint32 cmd_code            = 0;
    uint32 cmd_status          = 0;
    uint32 timeout             = 100;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "lchip is %u, flexe_shim_id is %u, inst_bmp is 0x%x\n", lchip, flexe_shim_id, inst_bmp);
    FLEXE_DUMP("\n Enter [FlexE] %s @ %d, lchip is %d, flexe_shim_id is %d, inst_bmp is 0x%x\n", __FUNCTION__, __LINE__, lchip, flexe_shim_id, inst_bmp);

    mcu_id = (flexe_shim_id == 0) ? 2 : 5;
    /*step1 : get cmd
     * cmd_code 
     * [15, 8] : inst_bmp
     * [3, 0] : enable
     */
    cmd_code |= (SYS_MCU_FLEXE_CMD_ENABLE_PAD_CFG << 0);
    cmd_code |= (inst_bmp << 1*8);

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "    %-12s = 0x%x\n", "cmd_code", cmd_code);
    FLEXE_DUMP("        mcu_id = %d, cmd_code = 0x%x\n", mcu_id, cmd_code);

    /*step2 : clear reg of cmd info */
    CTC_ERROR_RETURN(sys_tmm_mcu_write_shared_memory(lchip, mcu_id, GLB_INFO_FLEXE_PADDING_CMD_STATUS, 0x0, 0x0));

    /*step3 : send cmd code to mcu, let mcu enable padding*/
    CTC_ERROR_RETURN(sys_tmm_mcu_write_shared_memory(lchip, mcu_id, GLB_INFO_FLEXE_CMD_CODE, 0x0, cmd_code));

    sal_task_sleep(10);
    /*step4 : wait mcu execute complete */
    while(--timeout)
    {
        sal_task_sleep(2);
        CTC_ERROR_RETURN(sys_tmm_mcu_read_shared_memory(lchip, mcu_id, GLB_INFO_FLEXE_PADDING_CMD_STATUS, 0x0, &cmd_status));
        FLEXE_DUMP("            timeout = %d, cmd_status = 0x%x\n", timeout, cmd_status);

        if(SYS_MCU_FLEXE_CMD_STATUS_DOING == cmd_status)
        {
            FLEXE_DUMP("        SYS_MCU_FLEXE_CMD_STATUS_DOING\n");
            continue;
        }
        else if(SYS_MCU_FLEXE_CMD_STATUS_DONE == cmd_status)
        {
            ret = CTC_E_NONE;
            FLEXE_DUMP("        SYS_MCU_FLEXE_CMD_STATUS_DONE\n");
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "    %-12s = 0x%x\n", "cmd_status", cmd_status);
            break;
        }
        else
        {
            ret = CTC_E_NOT_READY;
            FLEXE_DUMP("        SYS_MCU_FLEXE_CMD_STATUS_TIME_OUT or SYS_MCU_FLEXE_CMD_STATUS_FAIL\n");
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "    %-12s = 0x%x\n", "cmd_status", cmd_status);
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "    TimeOut %-12s = 0x%x\n", "cmd_status", cmd_status);
            break;
        }
    }

    if(timeout == 0)
    {
        ret = CTC_E_NOT_READY;

        CTC_ERROR_RETURN(sys_tmm_mcu_read_shared_memory(lchip, mcu_id, GLB_INFO_FLEXE_PADDING_CMD_STATUS, 0x0, &cmd_status));
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "    TimeOut %-12s = 0x%x\n", "cmd_status", cmd_status);
        FLEXE_DUMP("            timeout = %d, cmd_status = 0x%x\n", timeout, cmd_status);
    }

    return ret;
}

STATIC int32
_sys_tmm_flexe_set_padlock_interval(uint8 lchip, uint8 flexe_shim_id, uint8 asic_inst, uint32 interval)
{
    uint32          cmd   = 0;
    uint32          index = 0;
    uint32          step  = 0;
    uint32          tbl_id = 0;
    uint32          fld_id = 0;
    TxPadLockPeriodInst0_m   pad_lock;

    /* #1, calc index */
    index = DRV_INS(flexe_shim_id, 0);

    tbl_id = TxPadLockPeriodInst0_t;
    step = TxPadLockPeriodInst1_t - TxPadLockPeriodInst0_t;
    tbl_id += step*asic_inst;

    /* #2, read HW table */
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pad_lock));

    /* ##2.2. modify field value */
    /* ###2.2.1. */
    fld_id = TxPadLockPeriodInst0_val_f;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &interval, &pad_lock, flexe_shim_id, 0);

    /* #3, write HW table*/
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pad_lock));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_pad_removeal(uint8 lchip, sys_flexe_group_t* group_node, uint8 enable)
{
    uint8 i         = 0;
    uint8 phy_speed = 0;
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 step     = 0;
    uint32 factor   = 0;
    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    uint32 val32    = 0;
    RxPadRemovalModeInst0_m pad_removeal;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &phy_speed);

    /* #1, calc index */
    index = DRV_INS(group_node->flexe_shim_id, 0);

    step = RxPadRemovalModeInst1_t - RxPadRemovalModeInst0_t;
    for (i = 0; i < group_node->inst_cnt;i++)
    {
        factor = group_node->inst_list[i];
        tbl_id = RxPadRemovalModeInst0_t;
        tbl_id += step*factor;

        /* #2, read HW table */
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pad_removeal));

        /* ##2.2. modify field value */
        /* ###2.2.1. */
        fld_id = RxPadRemovalModeInst0_val_f;
        if (enable)
        {
            if (CTC_PORT_SPEED_50G == phy_speed)
            {
                val32 = 0x1;
            }
        }
        else
        {
            val32 = 0;
        }
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pad_removeal, group_node->flexe_shim_id, 0);

        /* #3, write HW table*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pad_removeal));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_bondmask(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, uint8 enable)
{
    uint32          cmd   = 0;
    uint32          index = 0;
    uint32          step  = 0;
    uint32          factor = 0;
    uint32          tbl_id = 0;
    uint32          fld_id = 0;
    uint32          val32  = 0;
    uint8           i = 0, j = 0;
    uint8           bondmask = 0;
    uint8           inst_bmp = 0;
    uint8           phy_speed = 0;
    uint8           phy_inst_cnt = 0;
    sys_flexe_phy_t* p_phy = NULL;
    TxCtlInst0_m            inst_ctl;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &phy_speed);
    phy_inst_cnt = SYS_TMM_FLEXE_PHY_2_INST_CNT(phy_speed);

    /********************************************************************************************
     -- Config BondMask
       *  TxCtlInst0.bondMask : multi-instance bond to ONE group
       *  TxCtlInst0.padEn : instance conneted PHY type: 50G, padEn = group_node->pad_en; 200G/400G, padEN = 1; 100G, padEn = 0;
       *  RxCtlInst0.bondMask : multi-instance bond to ONE group
       *  RxCtlInst0.padEn : instance conneted PHY type: 50G, padEn = group_node->pad_en; 200G/400G, padEN = 1; 100G, padEn = 0;
    *********************************************************************************************/

    /*************** TxCtlInst0 start! ****************/
    /* #1, calc index */
    index = DRV_INS(group_node->flexe_shim_id, 0);

    step = TxCtlInst1_t - TxCtlInst0_t;
    for (i = 0; i < group_node->phy_cnt;i++)
    {
        p_phy = &group_node->phy_list[i];
        for (j = 0; j < phy_inst_cnt; j++)
        {
            factor = p_phy->inst_base+j;
            tbl_id = (SYS_FLEXE_DIR_TX == dir) ? TxCtlInst0_t : RxCtlInst0_t;
            tbl_id += step*factor;

            inst_bmp |= (1 << factor);
            SYS_CONDITION_CONTINUE(!enable && (SYS_FLEXE_DIR_TX == dir));

            /* #2, read HW table */
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &inst_ctl));

            /* ##2.2. modify field value */
            /* ###2.2.1. */
            fld_id = TxCtlInst0_padEn_f;
            if (enable)
            {
                if (CTC_PORT_SPEED_50G == phy_speed)
                {
                    val32 = group_node->pad_en;
                }
                else if((CTC_PORT_SPEED_400G == phy_speed)
                    || (CTC_PORT_SPEED_200G == phy_speed))
                {
                    val32 = 1;
                }
                else
                {
                    val32 = 0;
                }
            }
            else
            {
                val32 = 0;
            }
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &inst_ctl, group_node->flexe_shim_id, 0);

            /* #3, write HW table*/
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &inst_ctl));
        }

    }

    /* set pad interval */
    if (!enable && SYS_FLEXE_DIR_TX == dir)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_mcu_padding_cfg(lchip, group_node->flexe_shim_id, inst_bmp));
    }

    /* set pad removeal */
    if (SYS_FLEXE_DIR_RX == dir)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_pad_removeal(lchip, group_node, enable));
    }

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        bondmask |= 1 << group_node->inst_list[i];
    }

    step = TxCtlInst1_t - TxCtlInst0_t;
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        factor = group_node->inst_list[i];
        /* #1, calc index */
        index = DRV_INS(group_node->flexe_shim_id, 0);

        /* #2, read HW table */
        tbl_id = (SYS_FLEXE_DIR_TX == dir) ? TxCtlInst0_t : RxCtlInst0_t;
        tbl_id += step*factor;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &inst_ctl));
        /* ##2.2. modify field value */
        /* ###2.2.1. */
        fld_id = TxCtlInst0_bondMask_f;
        if (enable)
        {
            val32 = bondmask;
        }
        else
        {
            val32 = 1 << factor;
        }
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &inst_ctl, group_node->flexe_shim_id, 0);

        /* #3, write HW table*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &inst_ctl));
    }

    /*************** TxCtlInst0 end! ****************/

    /* set pad interval */
    if (!enable && (SYS_FLEXE_DIR_TX == dir))
    {
        for (i = 0; i < group_node->phy_cnt;i++)
        {
            p_phy = &group_node->phy_list[i];
            for (j = 0; j < phy_inst_cnt; j++)
            {
                factor = p_phy->inst_base+j;
                CTC_ERROR_RETURN(_sys_tmm_flexe_set_padlock_interval(lchip, group_node->flexe_shim_id, factor, 163830));
            }
        }
    }

    return CTC_E_NONE;
}


STATIC int32
_sys_tmm_flexe_set_intleave(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, uint8 enable)
{
    uint32          cmd   = 0;
    uint32          index = 0;
    uint32          step  = 0;
    uint32          factor = 0;
    uint32          tbl_id = 0;
    uint32          fld_id = 0;
    uint32          val32  = 0;
    uint8           i = 0, j = 0;
    uint8           cs_id = 0;
    uint8           phy_speed = 0;
    uint8           phy_inst_cnt = 0;
    uint8           cs_200g_flag[2] = {0};
    sys_flexe_phy_t* p_phy = NULL;
    sys_flexe_group_t* p_group = NULL;
    ctc_slistnode_t* node = NULL;

    TxInterleaveCfgInst0_m  intlv_cfg;
    McPcsX8LanesMiscCfg_m   pcs_intlv;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /********************************************************************************************
     -- RxInterleaveCfgInst
     -- TxInterleaveCfgInst
       *  .opt: when 400G PHY, set to 1; 200 PHY, set to 0; 50G/100G PHY set to X
       *  .en: when 200G/400G PHY, set to 1
    *********************************************************************************************/

    /* scan all groups(which is the same flexe_shim_id) which has 200G PHY online */
    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->group_list, node)
    {
        p_group = _ctc_container_of(node, sys_flexe_group_t, head);
        SYS_CONDITION_CONTINUE(p_group->flexe_shim_id != group_node->flexe_shim_id);
        SYS_CONDITION_CONTINUE(!p_group->phy_cnt);
        _sys_tmm_flexe_get_group_phy_speed(lchip, p_group, &phy_speed);
        for (i = 0; i < p_group->phy_cnt;i++)
        {
            SYS_TMM_FLEXE_SERDES_2_CS(p_group->phy_list[i].logical_serdes_base, cs_id);
            if (CTC_PORT_SPEED_200G == phy_speed)
            {
                cs_200g_flag[cs_id%2] = 1;
            }
        }
    }

    FLEXE_DUMP("DP(Flexe shim) id is %d\n", group_node->flexe_shim_id);
    FLEXE_DUMP("cs_200g_flag[0] = %d\n", cs_200g_flag[0]);
    FLEXE_DUMP("cs_200g_flag[1] = %d\n", cs_200g_flag[1]);

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &phy_speed);
    phy_inst_cnt = SYS_TMM_FLEXE_PHY_2_INST_CNT(phy_speed);
    if (SYS_FLEXE_DIR_TX == dir)
    {
        for (i = 0; i < group_node->phy_cnt;i++)
        {
            SYS_TMM_FLEXE_SERDES_2_CS(group_node->phy_list[i].logical_serdes_base, cs_id);

            /*************** McPcsX8LanesMiscCfg start! ****************/
            index = DRV_INS(cs_id, 0);
            tbl_id = McPcsX8LanesMiscCfg_t;

            /* #2, read HW table */
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_intlv));

            /* ##2.2. modify field value */
            /* ###2.2.1. */
            val32 = cs_200g_flag[cs_id%2] ? 1 : 0;
            FLEXE_DUMP("Set McPcsX8LanesMiscCfg.%d.cfgMcPcsConvertTxInterleaveEn to %d\n", cs_id, val32);
            fld_id = McPcsX8LanesMiscCfg_cfgMcPcsConvertTxInterleaveEn_f;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_intlv, cs_id, 0);

            /* #3, write HW table*/
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_intlv));
            /*************** McPcsX8LanesMiscCfg end! ****************/
        }
    }

    index = DRV_INS(group_node->flexe_shim_id, 0);
    step = TxInterleaveCfgInst1_t - TxInterleaveCfgInst0_t;

    for (i = 0; i < group_node->phy_cnt;i++)
    {
        p_phy = &group_node->phy_list[i];
        for (j = 0; j < phy_inst_cnt; j++)
        {
            factor = p_phy->inst_base+j;
            /*************** TxInterleaveCfgInst start! ****************/
            tbl_id = (SYS_FLEXE_DIR_TX == dir) ? TxInterleaveCfgInst0_t : RxInterleaveCfgInst0_t;
            tbl_id += step*factor;

            /* #2, read HW table */
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &intlv_cfg));

            /* ##2.2. modify field value */
            /* ###2.2.1. */
            val32 = 0;
            if (enable && (CTC_PORT_SPEED_400G == phy_speed))
            {
                val32 = 1;
            }
            fld_id = TxInterleaveCfgInst0_opt_f;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &intlv_cfg, group_node->flexe_shim_id, 0);

            if (enable && \
                ((CTC_PORT_SPEED_400G == phy_speed) || \
                    ((SYS_FLEXE_DIR_RX == dir) && (CTC_PORT_SPEED_200G == phy_speed)))\
                )
            {
                val32 = 1;
            }
            fld_id = TxInterleaveCfgInst0_en_f;
            FLEXE_DUMP("Set %sInterleaveCfgInst.%d.en value %d\n", (SYS_FLEXE_DIR_RX == dir)?"RX":"TX", factor, val32);
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &intlv_cfg, group_node->flexe_shim_id, 0);

            /* #3, write HW table*/
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &intlv_cfg));
            /*************** TxInterleaveCfgInst end! ****************/
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_pcs_cal(uint8 lchip, sys_flexe_group_t* group_node)
{
    const uint32 walk_end       = 7; /* walker end is always 7*/
    uint32  cmd                 = 0;
    uint32  index               = 0;
    uint8   i                   = 0;
    uint32  table               = 0;
    uint32  field               = 0;
    uint8   cs_glb_id           = 0;
    uint8   cs_perdp_id         = 0;
    uint8   pcs_idx             = 0;
    uint8   phy_speed           = 0;
    uint8   phy_lane_num        = 0;
    uint32  cal_entry_50[8]     = {0, 4, 2, 6, 1, 5, 3, 7};  /* index: CalEntry, value: PHY id */
    uint32  cal_entry_100[8]    = {0, 4, 2, 6, 0, 4, 2, 6};  /* index: CalEntry, value: PHY id */
    uint32  cal_entry_200[8]    = {0, 4, 0, 4, 0, 4, 0, 4};  /* index: CalEntry, value: PHY id */
    uint32  cal_entry_400[8]    = {0, 0, 0, 0, 0, 0, 0, 0};  /* index: CalEntry, value: PHY id */

    uint32  cal_entry_cur[2][8] = {{0}};  /* index: CalEntry, value: PHY id */
    uint32  cal_entry_new[2][8] = {{0}};  /* index: CalEntry, value: PHY id */

    McPcsX8LanesTxCal_m       pcs_entry;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &phy_speed);
    SYS_FLEXE_MODE_2_LANE_NUM(group_node->phy_list[0].pcs_mode, phy_lane_num);

    table = McPcsX8LanesTxCal_t;
    field = McPcsX8LanesTxCal_calEntry_f;

    /* read current entry */ 
    for (cs_perdp_id = 0; cs_perdp_id < 2; cs_perdp_id++)
    {
        cs_glb_id = group_node->flexe_shim_id*2 + cs_perdp_id;
        for (i = 0; i <= walk_end; i++)
        {
            index = DRV_INS(cs_glb_id, i);
            cmd = DRV_IOR(table, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_entry));
            DRV_IOR_FIELD(lchip, table, field, &cal_entry_cur[cs_perdp_id][i], &pcs_entry);
            cal_entry_new[cs_perdp_id][i] = cal_entry_cur[cs_perdp_id][i];
        }
    }

    for (i = 0; i < group_node->phy_cnt; i++)
    {
        SYS_TMM_FLEXE_SERDES_2_CS(group_node->phy_list[i].logical_serdes_base, cs_glb_id);
        pcs_idx = group_node->phy_list[i].logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS;
        cs_perdp_id = cs_glb_id % 2;

        FLEXE_DBG_PRINTF("i %d, cs %d, pcs lane %d, speed %d, if_type %d\n", i, cs_glb_id, pcs_idx, group_node->phy[i].if_mode.speed, group_node->phy[i].if_mode.interface_type);

        if (CTC_PORT_SPEED_50G == phy_speed)
        {
            if (2 == phy_lane_num)
            {
                switch (pcs_idx)
                {
                case 0:
                    cal_entry_new[cs_perdp_id][0] = cal_entry_50[0];
                    cal_entry_new[cs_perdp_id][4] = cal_entry_50[4];
                    break;
                case 2:
                    cal_entry_new[cs_perdp_id][2] = cal_entry_50[2];
                    cal_entry_new[cs_perdp_id][6] = cal_entry_50[6];
                    break;
                case 4:
                    cal_entry_new[cs_perdp_id][1] = cal_entry_50[1];
                    cal_entry_new[cs_perdp_id][5] = cal_entry_50[5];
                    break;
                case 6:
                    cal_entry_new[cs_perdp_id][3] = cal_entry_50[3];
                    cal_entry_new[cs_perdp_id][7] = cal_entry_50[7];
                    break;
                default:
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] Phy ID %d not exist! \n", pcs_idx);
                    return CTC_E_NOT_EXIST;
                }
            }
            else if (1 == phy_lane_num)
            {
                switch (pcs_idx)
                {
                case 0:
                    cal_entry_new[cs_perdp_id][0] = cal_entry_50[0];
                    break;
                case 1:
                    cal_entry_new[cs_perdp_id][4] = cal_entry_50[4];
                    break;
                case 2:
                    cal_entry_new[cs_perdp_id][2] = cal_entry_50[2];
                    break;
                case 3:
                    cal_entry_new[cs_perdp_id][6] = cal_entry_50[6];
                    break;
                case 4:
                    cal_entry_new[cs_perdp_id][1] = cal_entry_50[1];
                    break;
                case 5:
                    cal_entry_new[cs_perdp_id][5] = cal_entry_50[5];
                    break;
                case 6:
                    cal_entry_new[cs_perdp_id][3] = cal_entry_50[3];
                    break;
                case 7:
                    cal_entry_new[cs_perdp_id][7] = cal_entry_50[7];
                    break;
                default:
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] Phy ID %d not exist! \n", pcs_idx);
                    return CTC_E_NOT_EXIST;
                }
            }
        }
        else if (CTC_PORT_SPEED_100G == phy_speed)
        {
            if (2 == phy_lane_num)
            {
                switch (pcs_idx)
                {
                case 0:
                    cal_entry_new[cs_perdp_id][0] = cal_entry_100[0];
                    cal_entry_new[cs_perdp_id][4] = cal_entry_100[4];
                    break;
                case 2:
                    cal_entry_new[cs_perdp_id][2] = cal_entry_100[2];
                    cal_entry_new[cs_perdp_id][6] = cal_entry_100[6];
                    break;
                case 4:
                    cal_entry_new[cs_perdp_id][1] = cal_entry_100[1];
                    cal_entry_new[cs_perdp_id][5] = cal_entry_100[5];
                    break;
                case 6:
                    cal_entry_new[cs_perdp_id][3] = cal_entry_100[3];
                    cal_entry_new[cs_perdp_id][7] = cal_entry_100[7];
                    break;
                default:
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] Phy ID %d not exist! \n", pcs_idx);
                    return CTC_E_NOT_EXIST;
                }
            }
            else if (4 == phy_lane_num)
            {
                switch (pcs_idx)
                {
                case 0:
                    cal_entry_new[cs_perdp_id][0] = cal_entry_100[0];
                    cal_entry_new[cs_perdp_id][4] = cal_entry_100[4];
                    cal_entry_new[cs_perdp_id][2] = cal_entry_100[2];
                    cal_entry_new[cs_perdp_id][6] = cal_entry_100[6];
                    break;
                case 4:
                    cal_entry_new[cs_perdp_id][1] = cal_entry_100[1];
                    cal_entry_new[cs_perdp_id][5] = cal_entry_100[5];
                    cal_entry_new[cs_perdp_id][3] = cal_entry_100[3];
                    cal_entry_new[cs_perdp_id][7] = cal_entry_100[7];
                    break;
                default:
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] Phy ID %d not exist! \n", pcs_idx);
                    return CTC_E_NOT_EXIST;
                }
            }
        }
        else if (CTC_PORT_SPEED_200G == phy_speed)
        {
            switch (pcs_idx)
            {
            case 0:
                cal_entry_new[cs_perdp_id][0] = cal_entry_200[0];
                cal_entry_new[cs_perdp_id][4] = cal_entry_200[4];
                cal_entry_new[cs_perdp_id][2] = cal_entry_200[2];
                cal_entry_new[cs_perdp_id][6] = cal_entry_200[6];
                break;
            case 4:
                cal_entry_new[cs_perdp_id][1] = cal_entry_200[1];
                cal_entry_new[cs_perdp_id][5] = cal_entry_200[5];
                cal_entry_new[cs_perdp_id][3] = cal_entry_200[3];
                cal_entry_new[cs_perdp_id][7] = cal_entry_200[7];
                break;
            default:
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] Phy ID %d not exist! \n", pcs_idx);
                return CTC_E_NOT_EXIST;
            }
        }
        else if (CTC_PORT_SPEED_400G == phy_speed)
        {
            switch (pcs_idx)
            {
            case 0:
                cal_entry_new[cs_perdp_id][0] = cal_entry_400[0];
                cal_entry_new[cs_perdp_id][4] = cal_entry_400[4];
                cal_entry_new[cs_perdp_id][2] = cal_entry_400[2];
                cal_entry_new[cs_perdp_id][6] = cal_entry_400[6];
                cal_entry_new[cs_perdp_id][1] = cal_entry_400[1];
                cal_entry_new[cs_perdp_id][5] = cal_entry_400[5];
                cal_entry_new[cs_perdp_id][3] = cal_entry_400[3];
                cal_entry_new[cs_perdp_id][7] = cal_entry_400[7];
                break;
            default:
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] Phy ID %d not exist! \n", pcs_idx);
                return CTC_E_NOT_EXIST;
            }
        }
    }

    /*write new entry*/
    for (cs_perdp_id = 0; cs_perdp_id < 2; cs_perdp_id++)
    {
        cs_glb_id = group_node->flexe_shim_id*2 + cs_perdp_id;
        for (i = 0; i <= walk_end; i++)
        {
            if (cal_entry_new[cs_perdp_id][i] != cal_entry_cur[cs_perdp_id][i])
            {
                index = DRV_INS(cs_glb_id, i);

                DRV_IOW_FIELD_NZ(lchip, table, field, &cal_entry_new[cs_perdp_id][i], &pcs_entry, cs_glb_id, i);

                cmd = DRV_IOW(table, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_entry));
            }
        }
    }

    return CTC_E_NONE;
}

int32
_sys_tmm_flexe_pcs_common_calendar(uint8 lchip, uint8 cs_id, uint8 *p_error, uint16 *p_walk_end, uint16 *p_cal)
{
    uint8  i                    = 0;
    int32  ret                  = CTC_E_NONE;
    int16  cal_entry_num        = 8;
    uint8  speed                = 0;
    uint32 *speed_val_list      = NULL;
    uint8  base_logical_serdes  = 0;
    uint8  lane_num             = 0;
    sys_datapath_serdes_info_t* p_serdes = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    SYS_FLEXE_CS_2_BASE_LOGIC_SERDES(cs_id, base_logical_serdes);
    speed_val_list = (uint32*)mem_malloc(MEM_DMPS_MODULE, TMM_MAX_SERDES_NUM_PER_CS * sizeof(uint32));
    if(NULL == speed_val_list)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(speed_val_list, 0, TMM_MAX_SERDES_NUM_PER_CS * sizeof(uint32));

    for(i = 0; i < TMM_MAX_SERDES_NUM_PER_CS; i++)
    {
        CTC_ERROR_GOTO(sys_usw_datapath_get_serdes_info(lchip, (base_logical_serdes+i), &p_serdes), ret, RELEASE_PTR_RETURN);
        SYS_FLEXE_MODE_2_LANE_NUM(p_serdes->mode, lane_num);
        SYS_CONDITION_CONTINUE(!lane_num);
        SYS_CONDITION_CONTINUE(i % lane_num);
        SYS_FLEXE_MODE_2_SPEED(p_serdes->mode, speed);
        SYS_FLEXE_SPEED_2_VAL(speed, speed_val_list[i]);
    }

    CTC_ERROR_GOTO(_sys_tmm_datapath_common_calendar(cal_entry_num, TMM_MAX_SERDES_NUM_PER_CS, speed_val_list, 
                                                         p_error, p_walk_end, p_cal), ret, RELEASE_PTR_RETURN);

RELEASE_PTR_RETURN:
    mem_free(speed_val_list);

    return ret;
}

STATIC int32
_sys_tmm_flexe_pcs_cal_cfg(uint8 lchip, uint8 cs_id, uint16 walk_end, uint16 *cal)
{
    uint8  i      = 0;
    uint32 table  = 0;
    uint32 field  = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;
    uint32 is_back_cal = 0;
    McPcsX8LanesTxCalCtrl_m   pcs_cal_ctrl;
    McPcsX8LanesTxCal_m       pcs_entry;

    index = DRV_INS(cs_id, 0);

    table = McPcsX8LanesTxCalCtrl_t;
    cmd = DRV_IOR(table, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_cal_ctrl));
    val32 = GetMcPcsX8LanesTxCalCtrl(V, cfgMcPcsTxReady_f, &pcs_cal_ctrl);
    is_back_cal = GetMcPcsX8LanesTxCalCtrl(V, cfgCalEntrySel_f, &pcs_cal_ctrl);
    if (!val32)
        is_back_cal = 0;
    else
        is_back_cal = is_back_cal ? 0 : 1;

    /* walkend */
    field = (is_back_cal ? McPcsX8LanesTxCalCtrl_cfgWalkerEndBak_f : McPcsX8LanesTxCalCtrl_cfgWalkerEnd_f);
    val32 = walk_end;
    DRV_IOW_FIELD_NZ(lchip, table, field, &val32, &pcs_cal_ctrl, cs_id, 0);
    cmd = DRV_IOW(table, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_cal_ctrl));

    /* cal entry */
    table = (is_back_cal ? McPcsX8LanesTxCalBak_t : McPcsX8LanesTxCal_t);
    field = (is_back_cal ? McPcsX8LanesTxCalBak_calEntry_f : McPcsX8LanesTxCal_calEntry_f);
    for (i = 0; i <= walk_end; i++)
    {
        index = DRV_INS(cs_id, i);
        cmd = DRV_IOR(table, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_entry));
        val32 = cal[i];
        FLEXE_DUMP("cal[%d] = %d\n", i, cal[i]);
        DRV_IOW_FIELD_NZ(lchip, table, field, &val32, &pcs_entry, cs_id, i);
        cmd = DRV_IOW(table, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_entry));
    }

    /* entry sel */
    index = DRV_INS(cs_id, 0);
    table = McPcsX8LanesTxCalCtrl_t;
    field = McPcsX8LanesTxCalCtrl_cfgCalEntrySel_f;
    cmd = DRV_IOR(table, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_cal_ctrl));
    val32 = is_back_cal;
    DRV_IOW_FIELD_NZ(lchip, table, field, &val32, &pcs_cal_ctrl, cs_id, 0);
    cmd = DRV_IOW(table, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_cal_ctrl));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_pcs_cal_800m(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint8  i        = 0;
    uint8  j        = 0;
    uint8  error    = 0;
    int32  ret      = CTC_E_NONE;
    uint16 walk_end = 0;
    uint16* cal     = NULL;
    uint8  cs_pos   = 0;  /* 0-CS0/2, 1-CS1/3 */
    uint8  cs_valid[2] = {0};

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    FLEXE_DUMP("Enter new PCS cal\n");
    cal = (uint16*)mem_malloc(MEM_DMPS_MODULE, (SYS_TMM_MAX_CAL_LEN*2) * sizeof(uint16));
    if(NULL == cal)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(cal, 0, (SYS_TMM_MAX_CAL_LEN*2) * sizeof(uint16));

    for (i = 0; i < group_node->phy_cnt; i++)
    {
        FLEXE_DUMP("i = %d, valid\n", i);
        cs_pos = group_node->phy_list[i].logical_serdes_base / TMM_MAX_SERDES_NUM_PER_CS;
        cs_valid[cs_pos] = 1;
        FLEXE_DUMP("cs_valid %d is %d\n", cs_pos, cs_valid[cs_pos]);
    }
    for (i = 0; i < 2; i++)
    {
        if (cs_valid[i])
        {
            CTC_ERROR_GOTO(_sys_tmm_flexe_pcs_common_calendar(lchip, (group_node->flexe_shim_id*2+i), \
                &error, &walk_end, cal), ret, RELEASE_PTR);
            FLEXE_DUMP("cs %d walk_end = %d\n", (group_node->flexe_shim_id*2+i), walk_end);
            for (j = 0; j <= walk_end; j++)
            {
                FLEXE_DUMP("cal[%d] = %d\n", j, cal[j]);
            }
            CTC_ERROR_GOTO(_sys_tmm_flexe_pcs_cal_cfg(lchip, (group_node->flexe_shim_id*2+i), walk_end, cal), \
                ret, RELEASE_PTR);
        }
    }

RELEASE_PTR:
    mem_free(cal);

    return ret;
}

STATIC int32
_sys_tmm_flexe_set_group_config(uint8 lchip, sys_flexe_group_t *group_node, uint8 enable)
{
    uint32 core_freq = 0;

    if (enable)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_soc2p1(lchip, group_node, TRUE));

        CTC_ERROR_RETURN(_sys_tmm_flexe_set_bondmask(lchip, group_node, SYS_FLEXE_DIR_RX, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_bondmask(lchip, group_node, SYS_FLEXE_DIR_TX, TRUE));

        CTC_ERROR_RETURN(_sys_tmm_flexe_set_intleave(lchip, group_node, SYS_FLEXE_DIR_RX, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_intleave(lchip, group_node, SYS_FLEXE_DIR_TX, TRUE));

        core_freq = sys_usw_datapath_get_core_clock(lchip, 0);
        FLEXE_DUMP("core_freq = %d\n", core_freq);
        if (1050 == core_freq)
        {
            FLEXE_DUMP("Enter traditional PCS cal\n");
            CTC_ERROR_RETURN(_sys_tmm_flexe_set_pcs_cal(lchip, group_node));
        }
        else
        {
            FLEXE_DUMP("Enter 800M PCS cal\n");
            CTC_ERROR_RETURN(_sys_tmm_flexe_set_pcs_cal_800m(lchip, group_node));
        }
    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_intleave(lchip, group_node, SYS_FLEXE_DIR_RX, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_intleave(lchip, group_node, SYS_FLEXE_DIR_TX, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_bondmask(lchip, group_node, SYS_FLEXE_DIR_RX, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_bondmask(lchip, group_node, SYS_FLEXE_DIR_TX, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_soc2p1(lchip, group_node, FALSE));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_mgr_en(uint8 lchip, sys_flexe_group_t* group_node, uint8 enable)
{
    uint8 i = 0 , j = 0;
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;
    uint8 inst_id       = 0;
    uint8 flexe_shim_id = 0;
    uint8 phy_speed     = 0;
    FlexeMgrSoftRst_m  cm;

    flexe_shim_id = group_node->flexe_shim_id;
    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &phy_speed);

    tbl_id = FlexeMgrSoftRst_t;
    index = DRV_INS(flexe_shim_id, 0);

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));

    /* Field #1 begin */
    fld_id = FlexeMgrSoftRst_softRstOh_f;
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &cm);
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        inst_id = group_node->inst_list[i];
        if(enable)
        {
            val32 &= ~(1 << inst_id);
        }
        else
        {
            val32 |= (1 << inst_id);
        }
    }
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &cm, flexe_shim_id, 0);
    /* Field #1 end */

    /* Field #2/#3 begin*/
    for (i = 0; i < SYS_FLEXE_DIR_MAX; i++)
    {
        fld_id = ((SYS_FLEXE_DIR_RX == i) ? FlexeMgrSoftRst_softRstRx_f : FlexeMgrSoftRst_softRstTx_f);
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &cm);
        for (j = 0; j < group_node->inst_cnt; j++)
        {
            inst_id = group_node->inst_list[j];
            if(enable)
            {
                val32 &= ~(1 << inst_id);    /* section2section */
                val32 &= ~(1 << (8+inst_id));    /* sync */
                val32 &= ~(1 << (16+inst_id));   /* shim2shim */
            }
            else
            {
                val32 |= (1 << inst_id);    /* section2section */
                val32 |= (1 << (8+inst_id));    /* sync */
                val32 |= (1 << (16+inst_id));   /* shim2shim */
            }
        }
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &cm, flexe_shim_id, 0);
    }
    /* Field #2/#3 end */

    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_manual_switch_en(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, uint8 switch_en)
{
    uint8 i                 = 0;
    uint32 inst_id          = 0;
    uint32 tbl_id           = 0;
    uint32 fld_id           = 0;
    uint32 cmd              = 0;
    uint32 index            = 0;
    uint32 val32            = 0;
    uint32 step             = 0;
    uint32 factor           = 0;
    uint32 mask             = 0;

    FlexeMgrTsCfg_m  mgr_tscfg;
    FlexeMgrReserved_m  mgr_reserved;

    if (SYS_FLEXE_DIR_TX == dir)
    {
        /* #1, calc index */
        index = DRV_INS(group_node->flexe_shim_id, 0);

        /* #2, read HW table */
        tbl_id = FlexeMgrTsCfg_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mgr_tscfg));

        /* #3. modify field value */
        for (i = 0; i < group_node->inst_cnt; i++)
        {
            inst_id = group_node->inst_list[i];
            if (0 == inst_id % 2)
            {
                factor = inst_id / 2;
                step = FlexeMgrTsCfg_cfgPhyModeSel_1_pmaMode_f - FlexeMgrTsCfg_cfgPhyModeSel_0_pmaMode_f;
                fld_id = FlexeMgrTsCfg_cfgPhyModeSel_0_pmaMode_f + step*factor;
            }
            else
            {
                factor = inst_id / 2;
                step = FlexeMgrTsCfg_cfgPhyModeSel_1_pam4Mode_f - FlexeMgrTsCfg_cfgPhyModeSel_0_pam4Mode_f;
                fld_id = FlexeMgrTsCfg_cfgPhyModeSel_0_pam4Mode_f + step*factor;
            }
            val32 = switch_en ? 1 : 0;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mgr_tscfg, group_node->flexe_shim_id, 0);
        }

        /* #4, write HW table */
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mgr_tscfg));
    }
    else
    {
        /* #1, calc index */
        index = DRV_INS(group_node->flexe_shim_id, 0);

        /* #2, read HW table */
        tbl_id = FlexeMgrReserved_t;
        fld_id = FlexeMgrReserved_reserved_f;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mgr_reserved));
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &mgr_reserved);

        /* #3. modify field value */
        for (i = 0; i < group_node->inst_cnt; i++)
        {
            fld_id = FlexeMgrReserved_reserved_f;
            mask = 24 + group_node->inst_list[i];
            if(switch_en)
            {
                val32 |= (1 << mask);
            }
            else
            {
                val32 &= ~(1 << mask);
            }
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mgr_reserved, group_node->flexe_shim_id, 0);
        }

        /* #4, write HW table */
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mgr_reserved));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_manual_switch_sel(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, uint8 switch_sel)
{
    uint8 i                 = 0;
    uint8 inst_id           = 0;
    uint32 tbl_id           = 0;
    uint32 fld_id           = 0;
    uint32 cmd              = 0;
    uint32 index            = 0;
    uint32 val32            = 0;
    uint32 mask             = 0;

    FlexeMgrReserved_m  mgr_reserved;

    /* #1, calc index */
    index = DRV_INS(group_node->flexe_shim_id, 0);

    /* #2, read HW table */
    tbl_id = FlexeMgrReserved_t;
    fld_id = FlexeMgrReserved_reserved_f;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mgr_reserved));
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &mgr_reserved);

    /* #3, write HW table */
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        inst_id = group_node->inst_list[i];
        mask = (SYS_FLEXE_DIR_TX == dir) ? (8 + inst_id) : (16 + inst_id);
        if(switch_sel)
        {
            val32 |= (1 << mask);
        }
        else
        {
            val32 &= ~(1 << mask);
        }
    }

    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mgr_reserved, group_node->flexe_shim_id, 0);
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mgr_reserved));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_read_ohram_per_fld(uint8 lchip, uint8 flexe_shim_id, uint8 frame_id, uint8 asic_inst, 
                                          sys_flexe_oh_field_t oh_field, uint32* p_val, sys_flexe_dir_t dir)
{
    uint32 tbl_id = (SYS_FLEXE_DIR_RX == dir) ? 
                    (RxOhFrameRamInst0_t + (RxOhFrameRamInst1_t - RxOhFrameRamInst0_t) * asic_inst) : 
                    (TxOhFrameRamInst0_t + (TxOhFrameRamInst1_t - TxOhFrameRamInst0_t) * asic_inst);
    uint32 entry     = 0;
    uint32 index     = 0;
    uint32 cmd       = 0;
    uint32 val32_raw = 0;
    uint32 mask      = 0;
    uint32 start_bit = 0;
    RxOhFrameRamInst0_m  oh_ram;

    entry = g_flexe_oh_field_info[oh_field][FLEXE_OH_INFO_HALF_BLK_ID] + frame_id * SYS_FLEXE_OHRAM_BLKNUM;
    index = DRV_INS(flexe_shim_id, entry);
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &oh_ram));
    DRV_IOR_FIELD(lchip, tbl_id, RxOhFrameRamInst0_ohFrame_f, &val32_raw, &oh_ram);

    mask = ~(g_flexe_oh_field_info[oh_field][FLEXE_OH_INFO_MASK]);
    start_bit = g_flexe_oh_field_info[oh_field][FLEXE_OH_INFO_START_BIT];
    *p_val = (val32_raw & mask) >> start_bit;

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_group_table(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, uint32 *p_val)
{
    uint8  i                = 0;
    uint32 tbl_id           = 0;
    uint32 fld_id           = 0;
    uint32 cmd              = 0;
    uint32 index            = 0;
    uint32 val32            = 0;
    uint32 step             = 0;
    uint32 asic_inst        = 0;
    uint32 err              = 0;
    uint32 val[SYS_FLEXE_MAX_INST_CNT] = {0};

    RxOhblkLossCntInst0_m  cm;

    /* #1, calc index */
    index = DRV_INS(group_node->flexe_shim_id, 0);

    /* #2, read HW table */
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        asic_inst = group_node->inst_list[i];
        step = RxOhblkLossCntInst1_t - RxOhblkLossCntInst0_t; 
        tbl_id = RxOhblkLossCntInst0_t + step*asic_inst;
        fld_id = RxOhblkLossCntInst0_val_f;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &cm);
        if (SYS_FLEXE_DIR_TX == dir)
        {
            val[i] = (val32 >> 30) & 1;
        }
        else
        {
            val[i] = (val32 >> 31) & 1;
        }
        if ((i > 0) && (val[i] != val[0]))
        {
            err = 10;
        }
    }

    if (p_val)
    {
        *p_val = val[0] + err;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_sch_config_clear(uint8 lchip, sys_flexe_group_t* group_node, uint8 cycle_value, sys_flexe_dir_t dir)
{
    uint8 i = 0;
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 step_t   = 0;
    uint32 step_f   = 0;
    uint32 factor_f = 0;
    uint32 val32  = 0;

    sys_flexe_group_dir_t *p_group_dir = NULL;

    TxClientSch0ALow_m    client_sch;
    TxClientChidCycle0A_m chid;

    //SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, group %d dir %s clear sch config\n", __FUNCTION__, __LINE__, \
        group_node->group_id, dir?"TX":"RX");

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    /* #1, calc index */
    index = DRV_INS(group_node->flexe_shim_id, 0);

    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)   /* different inst */
    {
        /********************* TxClientSch0ALow start! ***********************/
        /* ##2. calc table step */
        /* base table id, need add:
           if..else to select A/B
           if..else to select low/high
        */
        step_t = TxClientSch1ALow_t - TxClientSch0ALow_t;
        if (SYS_FLEXE_DIR_TX == dir)
        {
            if (i < 4)
                tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? TxClientSch0ALow_t : TxClientSch0BLow_t;
            else
                tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? TxClientSch0AHigh_t : TxClientSch0BHigh_t;
        }
        else
        {
            if (i < 4)
                tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? RxClientSch0ALow_t : RxClientSch0BLow_t;
            else
                tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? RxClientSch0AHigh_t : RxClientSch0BHigh_t;
        }
        tbl_id += step_t * cycle_value;

        /* #2.1, read HW table */
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &client_sch));

        /* ##2.2. calc step */
        step_f = TxClientSch0ALow_subcalMask1_f - TxClientSch0ALow_subcalMask0_f;
        factor_f = i % 4;
        fld_id = TxClientSch0ALow_subcalMask0_f + step_f*factor_f;
        val32 = 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &client_sch, group_node->flexe_shim_id, 0);

        /* #3, write HW table */
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &client_sch));
        /********************* TxClientSch0ALow End! ***********************/
    }

    /********************* TxClientChidCycle0A start! ***********************/
    /* ##2. calc table step */
    if (SYS_FLEXE_DIR_TX == dir)
    {
        tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? TxClientChidCycle0A_t : TxClientChidCycle0B_t;
    }
    else
    {
        tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? RxClientChidCycle0A_t : RxClientChidCycle0B_t;
    }
    step_t = TxClientChidCycle1A_t - TxClientChidCycle0A_t;
    tbl_id += step_t * cycle_value;

    /* #2.1, read HW table */
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &chid));

    /* ##2.3. modify field value */
    fld_id = (SYS_FLEXE_DIR_TX == dir) ? TxClientChidCycle0A_chid_f : RxClientChidCycle0A_chid_f;
    val32 = 0;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &chid, group_node->flexe_shim_id, 0);

    /* #3, write HW table:*/
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &chid));
    /********************* TxClientChidCycle0A end! ***********************/

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_sch_config_sync(uint8 lchip, uint8 flexe_shim_id, uint8 ins_id, uint8 curr_A_or_B, uint8 cycle, sys_flexe_dir_t dir)
{
    uint32 index  = 0;
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 step_t = 0;
    uint32 step_f = 0;
    uint32 cmd    = 0;
    uint32 val32_curr = 0;
    TxClientSch0ALow_m     tx_client_sch_low;
    TxClientSch0AHigh_m    tx_client_sch_high;
    TxClientChidCycle0A_m  tx_chid;

    RxClientSch0ALow_m     rx_client_sch_low;
    RxClientSch0AHigh_m    rx_client_sch_high;
    RxClientChidCycle0A_m  rx_chid;

    //SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, shim %d asic_inst %d dir %s sync client sch config\n", __FUNCTION__, __LINE__, \
        flexe_shim_id, ins_id, dir?"TX":"RX");

    index = DRV_INS(flexe_shim_id, 0);

    if (SYS_FLEXE_DIR_TX == dir)
    {
        if (SYS_FLEXE_ACTIVE_B == curr_A_or_B)   /* B -> A */
        {
            if (ins_id < 4)
            {
                /********************* TxClientSch0ALow start! ***********************/
                /* step1: get active value */
                tbl_id = TxClientSch0BLow_t;
                step_t = TxClientSch1BLow_t - TxClientSch0BLow_t;
                tbl_id += step_t * cycle;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_client_sch_low));

                step_f = TxClientSch0BLow_subcalMask1_f - TxClientSch0BLow_subcalMask0_f;
                fld_id = TxClientSch0BLow_subcalMask0_f + step_f * ins_id;
                DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_curr, &tx_client_sch_low);
                /* step2: sync to backup */
                tbl_id = TxClientSch0ALow_t;
                step_t = TxClientSch1ALow_t - TxClientSch0ALow_t;
                tbl_id += step_t * cycle;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_client_sch_low));

                step_f = TxClientSch0ALow_subcalMask1_f - TxClientSch0ALow_subcalMask0_f;
                fld_id = TxClientSch0ALow_subcalMask0_f + step_f * ins_id;
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_curr, &tx_client_sch_low, flexe_shim_id, 0);

                cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_client_sch_low));
                /********************* TxClientSch0ALow end! ***********************/
            }
            else
            {
                /********************* TxClientSch0AHigh start! ***********************/
                /* step1: get active value */
                tbl_id = TxClientSch0BHigh_t;
                step_t = TxClientSch1BHigh_t - TxClientSch0BHigh_t;
                tbl_id += step_t * cycle;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_client_sch_high));

                step_f = TxClientSch0BHigh_subcalMask5_f - TxClientSch0BHigh_subcalMask4_f;
                fld_id = TxClientSch0BHigh_subcalMask4_f + step_f * (ins_id%4);
                DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_curr, &tx_client_sch_high);
                /* step2: sync to backup */
                tbl_id = TxClientSch0AHigh_t;
                step_t = TxClientSch1AHigh_t - TxClientSch0AHigh_t;
                tbl_id += step_t * cycle;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_client_sch_high));

                step_f = TxClientSch0AHigh_subcalMask5_f - TxClientSch0AHigh_subcalMask4_f;
                fld_id = TxClientSch0AHigh_subcalMask4_f + step_f * (ins_id%4);
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_curr, &tx_client_sch_high, flexe_shim_id, 0);

                cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_client_sch_high));
                /********************* TxClientSch0AHigh end! ***********************/
            }

            /********************* TxClientChidCycle0A start! ***********************/
            /* step1: get active value */
            tbl_id = TxClientChidCycle0B_t;
            step_t = TxClientChidCycle1B_t - TxClientChidCycle0B_t;
            tbl_id += step_t * cycle;

            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_chid));

            fld_id = TxClientChidCycle0B_chid_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_curr, &tx_chid);

            /* step2: sync to backup */
            tbl_id = TxClientChidCycle0A_t;
            step_t = TxClientChidCycle1A_t - TxClientChidCycle0A_t;
            tbl_id += step_t * cycle;

            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_chid));

            fld_id = TxClientChidCycle0A_chid_f;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_curr, &tx_chid, flexe_shim_id, 0);

            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_chid));
            /********************* TxClientChidCycle0A end! ***********************/
        }
        else  /* A -> B */
        {
            if (ins_id < 4)
            {
                /********************* TxClientSch0ALow start! ***********************/
                /* step1: get active value */
                tbl_id = TxClientSch0ALow_t;
                step_t = TxClientSch1ALow_t - TxClientSch0ALow_t;
                tbl_id += step_t * cycle;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_client_sch_low));

                step_f = TxClientSch0ALow_subcalMask1_f - TxClientSch0ALow_subcalMask0_f;
                fld_id = TxClientSch0ALow_subcalMask0_f + step_f * ins_id;
                DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_curr, &tx_client_sch_low);

                /* step2: sync to backup */
                tbl_id = TxClientSch0BLow_t;
                step_t = TxClientSch1BLow_t - TxClientSch0BLow_t;
                tbl_id += step_t * cycle;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_client_sch_low));

                step_f = TxClientSch0BLow_subcalMask1_f - TxClientSch0BLow_subcalMask0_f;
                fld_id = TxClientSch0BLow_subcalMask0_f + step_f * ins_id;
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_curr, &tx_client_sch_low, flexe_shim_id, 0);

                cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_client_sch_low));
                /********************* TxClientSch0ALow end! ***********************/
            }
            else
            {
                /********************* TxClientSch0AHigh start! ***********************/
                /* step1: get active value */
                tbl_id = TxClientSch0AHigh_t;
                step_t = TxClientSch1AHigh_t - TxClientSch0AHigh_t;
                tbl_id += step_t * cycle;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_client_sch_high));

                step_f = TxClientSch0AHigh_subcalMask5_f - TxClientSch0AHigh_subcalMask4_f;
                fld_id = TxClientSch0AHigh_subcalMask4_f + step_f * (ins_id%4);
                DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_curr, &tx_client_sch_high);

                /* step2: sync to backup */
                tbl_id = TxClientSch0BHigh_t;
                step_t = TxClientSch1BHigh_t - TxClientSch0BHigh_t;
                tbl_id += step_t * cycle;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_client_sch_high));

                step_f = TxClientSch0BHigh_subcalMask5_f - TxClientSch0BHigh_subcalMask4_f;
                fld_id = TxClientSch0BHigh_subcalMask4_f + step_f * (ins_id%4);
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_curr, &tx_client_sch_high, flexe_shim_id, 0);

                cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_client_sch_high));
                /********************* TxClientSch0AHigh end! ***********************/
            }

            /********************* TxClientChidCycle0A start! ***********************/
            /* step1: get active value */
            tbl_id = TxClientChidCycle0A_t;
            step_t = TxClientChidCycle1A_t - TxClientChidCycle0A_t;
            tbl_id += step_t * cycle;

            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_chid));

            fld_id = TxClientChidCycle0A_chid_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_curr, &tx_chid);

            /* step2: sync to backup */
            tbl_id = TxClientChidCycle0B_t;
            step_t = TxClientChidCycle1B_t - TxClientChidCycle0B_t;
            tbl_id += step_t * cycle;

            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_chid));

            fld_id = TxClientChidCycle0B_chid_f;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_curr, &tx_chid, flexe_shim_id, 0);

            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_chid));
            /********************* TxClientChidCycle0A end! ***********************/
        }
    }
    else  /* RX */
    {
        if (SYS_FLEXE_ACTIVE_B == curr_A_or_B)   /* B -> A */
        {
            if (ins_id < 4)
            {
                /********************* RxClientSch0ALow start! ***********************/
                /* step1: get active value */
                tbl_id = RxClientSch0BLow_t;
                step_t = RxClientSch1BLow_t - RxClientSch0BLow_t;
                tbl_id += step_t * cycle;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_client_sch_low));

                step_f = RxClientSch0BLow_subcalMask1_f - RxClientSch0BLow_subcalMask0_f;
                fld_id = RxClientSch0BLow_subcalMask0_f + step_f * ins_id;
                DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_curr, &rx_client_sch_low);
                /* step2: sync to backup */
                tbl_id = RxClientSch0ALow_t;
                step_t = RxClientSch1ALow_t - RxClientSch0ALow_t;
                tbl_id += step_t * cycle;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_client_sch_low));

                step_f = RxClientSch0ALow_subcalMask1_f - RxClientSch0ALow_subcalMask0_f;
                fld_id = RxClientSch0ALow_subcalMask0_f + step_f * ins_id;
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_curr, &rx_client_sch_low, flexe_shim_id, 0);

                cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_client_sch_low));
                /********************* RxClientSch0ALow end! ***********************/
            }
            else
            {
                /********************* RxClientSch0AHigh start! ***********************/
                /* step1: get active value */
                tbl_id = RxClientSch0BHigh_t;
                step_t = RxClientSch1BHigh_t - RxClientSch0BHigh_t;
                tbl_id += step_t * cycle;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_client_sch_high));

                step_f = RxClientSch0BHigh_subcalMask5_f - RxClientSch0BHigh_subcalMask4_f;
                fld_id = RxClientSch0BHigh_subcalMask4_f + step_f * (ins_id%4);
                DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_curr, &rx_client_sch_high);
                /* step2: sync to backup */
                tbl_id = RxClientSch0AHigh_t;
                step_t = RxClientSch1AHigh_t - RxClientSch0AHigh_t;
                tbl_id += step_t * cycle;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_client_sch_high));

                step_f = RxClientSch0AHigh_subcalMask5_f - RxClientSch0AHigh_subcalMask4_f;
                fld_id = RxClientSch0AHigh_subcalMask4_f + step_f * (ins_id%4);
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_curr, &rx_client_sch_high, flexe_shim_id, 0);

                cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_client_sch_high));
                /********************* RxClientSch0AHigh end! ***********************/
            }

            /********************* RxClientChidCycle0A start! ***********************/
            /* step1: get active value */
            tbl_id = RxClientChidCycle0B_t;
            step_t = RxClientChidCycle1B_t - RxClientChidCycle0B_t;
            tbl_id += step_t * cycle;

            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_chid));

            fld_id = RxClientChidCycle0B_chid_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_curr, &rx_chid);

            /* step2: sync to backup */
            tbl_id = RxClientChidCycle0A_t;
            step_t = RxClientChidCycle1A_t - RxClientChidCycle0A_t;
            tbl_id += step_t * cycle;

            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_chid));

            fld_id = RxClientChidCycle0A_chid_f;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_curr, &rx_chid, flexe_shim_id, 0);

            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_chid));
            /********************* RxClientChidCycle0A end! ***********************/
        }
        else  /* A -> B */
        {
            if (ins_id < 4)
            {
                /********************* RxClientSch0ALow start! ***********************/
                /* step1: get active value */
                tbl_id = RxClientSch0ALow_t;
                step_t = RxClientSch1ALow_t - RxClientSch0ALow_t;
                tbl_id += step_t * cycle;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_client_sch_low));

                step_f = RxClientSch0ALow_subcalMask1_f - RxClientSch0ALow_subcalMask0_f;
                fld_id = RxClientSch0ALow_subcalMask0_f + step_f * ins_id;
                DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_curr, &rx_client_sch_low);

                /* step2: sync to backup */
                tbl_id = RxClientSch0BLow_t;
                step_t = RxClientSch1BLow_t - RxClientSch0BLow_t;
                tbl_id += step_t * cycle;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_client_sch_low));

                step_f = RxClientSch0BLow_subcalMask1_f - RxClientSch0BLow_subcalMask0_f;
                fld_id = RxClientSch0BLow_subcalMask0_f + step_f * ins_id;
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_curr, &rx_client_sch_low, flexe_shim_id, 0);

                cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_client_sch_low));
                /********************* RxClientSch0ALow end! ***********************/
            }
            else
            {
                /********************* RxClientSch0AHigh start! ***********************/
                /* step1: get active value */
                tbl_id = RxClientSch0AHigh_t;
                step_t = RxClientSch1AHigh_t - RxClientSch0AHigh_t;
                tbl_id += step_t * cycle;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_client_sch_high));

                step_f = RxClientSch0AHigh_subcalMask5_f - RxClientSch0AHigh_subcalMask4_f;
                fld_id = RxClientSch0AHigh_subcalMask4_f + step_f * (ins_id%4);
                DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_curr, &rx_client_sch_high);
                /* step2: sync to backup */
                tbl_id = RxClientSch0BHigh_t;
                step_t = RxClientSch1BHigh_t - RxClientSch0BHigh_t;
                tbl_id += step_t * cycle;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_client_sch_high));

                step_f = RxClientSch0BHigh_subcalMask5_f - RxClientSch0BHigh_subcalMask4_f;
                fld_id = RxClientSch0BHigh_subcalMask4_f + step_f * (ins_id%4);
                DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_curr, &rx_client_sch_high, flexe_shim_id, 0);

                cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_client_sch_high));
                /********************* RxClientSch0AHigh end! ***********************/
            }

            /********************* RxClientChidCycle0A start! ***********************/
            /* step1: get active value */
            tbl_id = RxClientChidCycle0A_t;
            step_t = RxClientChidCycle1A_t - RxClientChidCycle0A_t;
            tbl_id += step_t * cycle;

            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_chid));

            fld_id = RxClientChidCycle0A_chid_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_curr, &rx_chid);

            /* step2: sync to backup */
            tbl_id = RxClientChidCycle0B_t;
            step_t = RxClientChidCycle1B_t - RxClientChidCycle0B_t;
            tbl_id += step_t * cycle;

            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_chid));

            fld_id = RxClientChidCycle0B_chid_f;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_curr, &rx_chid, flexe_shim_id, 0);

            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_chid));
            /********************* RxClientChidCycle0A end! ***********************/
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_sch_config(uint8 lchip, sys_flexe_group_t* group_node, uint8 cycle_value, sys_flexe_dir_t dir)
{
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 step_t   = 0;
    uint32 step_f   = 0;
    uint32 factor_f = 0;
    uint32 val32  = 0;
    uint8 i = 0;
    uint8 cc = 0;
    uint8  group_inst_offset = 0;
    int32 ret = CTC_E_NONE;
    sys_flexe_group_dir_t *p_group_dir = NULL;

    TxClientSch0ALow_m    client_sch;
    TxClientChidCycle0A_m chid;

    //SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, group %d dir %s client sch config\n", __FUNCTION__, __LINE__, \
        group_node->group_id, dir?"TX":"RX");

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    /********************************************************************************************
     -- tx mask, Low is inst0..3/ High is inst4..7
       * TxClientSch[0..79][A-B]Low.subCalMask[0..3]
       * TxClientSch[0..79][A-B]High.subCalMask[4..7]

     -- tx channel config
       * TxClientChidCycle[0..79][A-B].channelMode
       * TxClientChidCycle[0..79][A-B].chid

     -- rx mask
       * RxClientSch[0..79][A-B]Low.subCalMask[0..3]
       * RxClientSch[0..79][A-B]High.subCalMask[4..7]

     -- rx channel config
       * RxClientChidCycle[0..79][A-B].channelMode
       * RxClientChidCycle[0..79][A-B].chid
    *********************************************************************************************/

    ret = _sys_tmm_flexe_get_cc_by_cycle_value(lchip, group_node, cycle_value, dir, &cc);
    if (0 != ret)
    {
        return CTC_E_NONE;
    }

    /* #1, calc index */
    index = DRV_INS(group_node->flexe_shim_id, 0);

    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)   /* different inst */
    {
        ret = _sys_tmm_flexe_get_group_inst_offset_by_asic_inst(lchip, group_node, i, &group_inst_offset);
        SYS_CONDITION_CONTINUE(0 != ret);

        /********************* TxClientSch0ALow start! ***********************/
        /* ##2. calc table step */
        /* base table id, need add:
           if..else to select A/B
           if..else to select low/high
        */
        step_t = TxClientSch1ALow_t - TxClientSch0ALow_t;
        if (SYS_FLEXE_DIR_TX == dir)
        {
            if (i < 4)
                tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? TxClientSch0ALow_t : TxClientSch0BLow_t;
            else
                tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? TxClientSch0AHigh_t : TxClientSch0BHigh_t;
        }
        else
        {
            if (i < 4)
                tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? RxClientSch0ALow_t : RxClientSch0BLow_t;
            else
                tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? RxClientSch0AHigh_t : RxClientSch0BHigh_t;
        }
        tbl_id += step_t * cycle_value;

        /* #2.1, read HW table */
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &client_sch));

        /* ##2.2. calc step */
        step_f = TxClientSch0ALow_subcalMask1_f - TxClientSch0ALow_subcalMask0_f;
        factor_f = i % 4;
        fld_id = TxClientSch0ALow_subcalMask0_f + step_f*factor_f;
        val32 = p_group_dir->cc[cc].inst[group_inst_offset].cc_subcalmask;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &client_sch, group_node->flexe_shim_id, 0);

        /* #3, write HW table */
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &client_sch));
        /********************* TxClientSch0ALow End! ***********************/
    }

    /********************* TxClientChidCycle0A start! ***********************/
    /* ##2. calc table step */
    if (SYS_FLEXE_DIR_TX == dir)
    {
        tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? TxClientChidCycle0A_t : TxClientChidCycle0B_t;
    }
    else
    {
        tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? RxClientChidCycle0A_t : RxClientChidCycle0B_t;
    }
    step_t = TxClientChidCycle1A_t - TxClientChidCycle0A_t;
    tbl_id += step_t * cycle_value;

    /* #2.1, read HW table */
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &chid));

    /* ##2.3. modify field value */
    fld_id = (SYS_FLEXE_DIR_TX == dir) ? TxClientChidCycle0A_chid_f : RxClientChidCycle0A_chid_f;
    val32 = p_group_dir->cc[cc].shim_chid;
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &chid, group_node->flexe_shim_id, 0);

    /* #3, write HW table:*/
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &chid));
    /********************* TxClientChidCycle0A end! ***********************/

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_inst_sch_config_sync(uint8 lchip, uint8 flexe_shim_id, uint8 curr_A_or_B, uint8 ins_id, sys_flexe_dir_t dir)
{
    uint8  i          = 0;
    uint8  inst_cycle = 0;
    uint32 index  = 0;
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 step_t = 0;
    uint32 step_2 = 0;
    uint32 step_f = 0;
    uint32 cmd    = 0;
    uint32 val32_arr[SYS_FLEXE_MAX_SLOT_PER_INST] = {0};

    TxSch0AInst0_m              tx_inst_sch;
    TxChannelIdTable0AInst0_m   tx_inst_chid;

    RxSch0AInst0_m              rx_inst_sch;
    RxChidTable0AInst0_m        rx_inst_chid;

    //SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, shim %d asic_inst %d dir %s sync inst sch config\n", __FUNCTION__, __LINE__, \
        flexe_shim_id, ins_id, dir?"TX":"RX");

    index = DRV_INS(flexe_shim_id, 0);

    if (SYS_FLEXE_DIR_TX == dir)
    {
        if (SYS_FLEXE_ACTIVE_B == curr_A_or_B)  /* B -> A */
        {
            for (inst_cycle = 0; inst_cycle < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); inst_cycle++)
            {
                /********************* TxSch0BInst0 start! ***********************/
                /* step1: get active value */
                tbl_id = TxSch0BInst0_t;
                step_t = TxSch1BInst0_t - TxSch0BInst0_t;
                tbl_id += step_t * inst_cycle;
                step_2 = TxSch0BInst1_t - TxSch0BInst0_t;
                tbl_id += step_2 * ins_id;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_inst_sch));

                for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); i++)
                {
                    step_f = TxSch0BInst0_subcalMask1_f - TxSch0BInst0_subcalMask0_f;
                    fld_id = TxSch0BInst0_subcalMask0_f + step_f*i;
                    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_arr[i], &tx_inst_sch);
                }

                /* step2: sync to backup */
                tbl_id = TxSch0AInst0_t;
                step_t = TxSch1AInst0_t - TxSch0AInst0_t;
                tbl_id += step_t * inst_cycle;
                step_2 = TxSch0AInst1_t - TxSch0AInst0_t;
                tbl_id += step_2 * ins_id;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_inst_sch));

                for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); i++)
                {
                    step_f = TxSch0AInst0_subcalMask1_f - TxSch0AInst0_subcalMask0_f;
                    fld_id = TxSch0AInst0_subcalMask0_f + step_f*i;
                    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_arr[i], &tx_inst_sch, flexe_shim_id, 0);
                }

                cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_inst_sch));
                /********************* TxSch0BInst0 end! ***********************/

                /********************* TxChannelIdTable0BInst0 start! ***********************/
                /* step1: get active value */
                tbl_id = TxChannelIdTable0BInst0_t;
                step_t = TxChannelIdTable0BInst1_t - TxChannelIdTable0BInst0_t;
                tbl_id += step_t * ins_id;
                step_2 = TxChannelIdTable1BInst0_t - TxChannelIdTable0BInst0_t;
                tbl_id += step_2 * (inst_cycle/2);

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_inst_chid));

                for (i = 0; i < 2; i++)
                {
                    step_f = TxChannelIdTable0BInst0_cycle1Chid_f - TxChannelIdTable0BInst0_cycle0Chid_f;
                    fld_id = TxChannelIdTable0BInst0_cycle0Chid_f + step_f*i;
                    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_arr[i], &tx_inst_chid);
                }

                /* step2: sync to backup */
                tbl_id = TxChannelIdTable0AInst0_t;
                step_t = TxChannelIdTable0AInst1_t - TxChannelIdTable0AInst0_t;
                tbl_id += step_t * ins_id;
                step_2 = TxChannelIdTable1AInst0_t - TxChannelIdTable0AInst0_t;
                tbl_id += step_2 * (inst_cycle/2);

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_inst_chid));

                for (i = 0; i < 2; i++)
                {
                    step_f = TxChannelIdTable0AInst0_cycle1Chid_f - TxChannelIdTable0AInst0_cycle0Chid_f;
                    fld_id = TxChannelIdTable0AInst0_cycle0Chid_f + step_f*i;
                    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_arr[i], &tx_inst_chid, flexe_shim_id, 0);
                }

                /* #3, write HW table*/
                cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_inst_chid));
                /********************* TxChannelIdTable0BInst0 end! ***********************/
            }
        }
        else   /* A -> B */
        {
            for (inst_cycle = 0; inst_cycle < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); inst_cycle++)
            {
                /********************* TxSch0AInst0 start! ***********************/
                /* step1: get active value */
                tbl_id = TxSch0AInst0_t;
                step_t = TxSch1AInst0_t - TxSch0AInst0_t;
                tbl_id += step_t * inst_cycle;
                step_2 = TxSch0AInst1_t - TxSch0AInst0_t;
                tbl_id += step_2 * ins_id;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_inst_sch));

                for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); i++)
                {
                    step_f = TxSch0AInst0_subcalMask1_f - TxSch0AInst0_subcalMask0_f;
                    fld_id = TxSch0AInst0_subcalMask0_f + step_f*i;
                    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_arr[i], &tx_inst_sch);
                }

                /* step2: sync to backup */
                tbl_id = TxSch0BInst0_t;
                step_t = TxSch1BInst0_t - TxSch0BInst0_t;
                tbl_id += step_t * inst_cycle;
                step_2 = TxSch0BInst1_t - TxSch0BInst0_t;
                tbl_id += step_2 * ins_id;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_inst_sch));

                for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); i++)
                {
                    step_f = TxSch0BInst0_subcalMask1_f - TxSch0BInst0_subcalMask0_f;
                    fld_id = TxSch0BInst0_subcalMask0_f + step_f*i;
                    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_arr[i], &tx_inst_sch, flexe_shim_id, 0);
                }

                cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_inst_sch));
                /********************* TxSch0AInst0 end! ***********************/

                /********************* TxChannelIdTable0AInst0 start! ***********************/
                /* step1: get active value */
                tbl_id = TxChannelIdTable0AInst0_t;
                step_t = TxChannelIdTable0AInst1_t - TxChannelIdTable0AInst0_t;
                tbl_id += step_t * ins_id;
                step_2 = TxChannelIdTable1AInst0_t - TxChannelIdTable0AInst0_t;
                tbl_id += step_2 * (inst_cycle/2);

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_inst_chid));

                for (i = 0; i < 2; i++)
                {
                    step_f = TxChannelIdTable0AInst0_cycle1Chid_f - TxChannelIdTable0AInst0_cycle0Chid_f;
                    fld_id = TxChannelIdTable0AInst0_cycle0Chid_f + step_f*i;
                    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_arr[i], &tx_inst_chid);
                }

                /* step2: sync to backup */
                tbl_id = TxChannelIdTable0BInst0_t;
                step_t = TxChannelIdTable0BInst1_t - TxChannelIdTable0BInst0_t;
                tbl_id += step_t * ins_id;
                step_2 = TxChannelIdTable1BInst0_t - TxChannelIdTable0BInst0_t;
                tbl_id += step_2 * (inst_cycle/2);

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_inst_chid));

                for (i = 0; i < 2; i++)
                {
                    step_f = TxChannelIdTable0BInst0_cycle1Chid_f - TxChannelIdTable0BInst0_cycle0Chid_f;
                    fld_id = TxChannelIdTable0BInst0_cycle0Chid_f + step_f*i;
                    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_arr[i], &tx_inst_chid, flexe_shim_id, 0);
                }

                /* #3, write HW table*/
                cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_inst_chid));
                /********************* TxChannelIdTable0BInst0 end! ***********************/
            }
        }
    }
    else   /* RX */
    {
        if (SYS_FLEXE_ACTIVE_B == curr_A_or_B)  /* B -> A */
        {
            for (inst_cycle = 0; inst_cycle < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); inst_cycle++)
            {
                /********************* RxSch0BInst0 start! ***********************/
                /* step1: get active value */
                tbl_id = RxSch0BInst0_t;
                step_t = RxSch1BInst0_t - RxSch0BInst0_t;
                tbl_id += step_t * inst_cycle;
                step_2 = RxSch0BInst1_t - RxSch0BInst0_t;
                tbl_id += step_2 * ins_id;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_inst_sch));

                for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); i++)
                {
                    step_f = RxSch0BInst0_subcalMask1_f - RxSch0BInst0_subcalMask0_f;
                    fld_id = RxSch0BInst0_subcalMask0_f + step_f*i;
                    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_arr[i], &rx_inst_sch);
                }

                /* step2: sync to backup */
                tbl_id = RxSch0AInst0_t;
                step_t = RxSch1AInst0_t - RxSch0AInst0_t;
                tbl_id += step_t * inst_cycle;
                step_2 = RxSch0AInst1_t - RxSch0AInst0_t;
                tbl_id += step_2 * ins_id;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_inst_sch));

                for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); i++)
                {
                    step_f = RxSch0AInst0_subcalMask1_f - RxSch0AInst0_subcalMask0_f;
                    fld_id = RxSch0AInst0_subcalMask0_f + step_f*i;
                    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_arr[i], &rx_inst_sch, flexe_shim_id, 0);
                }

                cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_inst_sch));
                /********************* RxSch0BInst0 end! ***********************/

                /********************* RxChidTable0BInst0 start! ***********************/
                /* step1: get active value */
                tbl_id = RxChidTable0BInst0_t;
                step_t = RxChidTable0BInst1_t - RxChidTable0BInst0_t;
                tbl_id += step_t * ins_id;
                step_2 = RxChidTable1BInst0_t - RxChidTable0BInst0_t;
                tbl_id += step_2 * (inst_cycle/2);

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_inst_chid));

                for (i = 0; i < 2; i++)
                {
                    step_f = RxChidTable0BInst0_cycle1Chid_f - RxChidTable0BInst0_cycle0Chid_f;
                    fld_id = RxChidTable0BInst0_cycle0Chid_f + step_f*i;
                    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_arr[i], &rx_inst_chid);
                }

                /* step2: sync to backup */
                tbl_id = RxChidTable0AInst0_t;
                step_t = RxChidTable0AInst1_t - RxChidTable0AInst0_t;
                tbl_id += step_t * ins_id;
                step_2 = RxChidTable1AInst0_t - RxChidTable0AInst0_t;
                tbl_id += step_2 * (inst_cycle/2);

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_inst_chid));

                for (i = 0; i < 2; i++)
                {
                    step_f = RxChidTable0AInst0_cycle1Chid_f - RxChidTable0AInst0_cycle0Chid_f;
                    fld_id = RxChidTable0AInst0_cycle0Chid_f + step_f*i;
                    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_arr[i], &rx_inst_chid, flexe_shim_id, 0);
                }

                /* #3, write HW table*/
                cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_inst_chid));
                /********************* RxChidTable0BInst0 end! ***********************/
            }
        }
        else   /* A -> B */
        {
            for (inst_cycle = 0; inst_cycle < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); inst_cycle++)
            {
                /********************* RxSch0AInst0 start! ***********************/
                /* step1: get active value */
                tbl_id = RxSch0AInst0_t;
                step_t = RxSch1AInst0_t - RxSch0AInst0_t;
                tbl_id += step_t * inst_cycle;
                step_2 = RxSch0AInst1_t - RxSch0AInst0_t;
                tbl_id += step_2 * ins_id;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_inst_sch));

                for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); i++)
                {
                    step_f = RxSch0AInst0_subcalMask1_f - RxSch0AInst0_subcalMask0_f;
                    fld_id = RxSch0AInst0_subcalMask0_f + step_f*i;
                    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_arr[i], &rx_inst_sch);
                }

                /* step2: sync to backup */
                tbl_id = RxSch0BInst0_t;
                step_t = RxSch1BInst0_t - RxSch0BInst0_t;
                tbl_id += step_t * inst_cycle;
                step_2 = RxSch0BInst1_t - RxSch0BInst0_t;
                tbl_id += step_2 * ins_id;

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_inst_sch));

                for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); i++)
                {
                    step_f = RxSch0BInst0_subcalMask1_f - RxSch0BInst0_subcalMask0_f;
                    fld_id = RxSch0BInst0_subcalMask0_f + step_f*i;
                    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_arr[i], &rx_inst_sch, flexe_shim_id, 0);
                }

                cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_inst_sch));
                /********************* RxSch0AInst0 end! ***********************/

                /********************* RxChidTable0AInst0 start! ***********************/
                /* step1: get active value */
                tbl_id = RxChidTable0AInst0_t;
                step_t = RxChidTable0AInst1_t - RxChidTable0AInst0_t;
                tbl_id += step_t * ins_id;
                step_2 = RxChidTable1AInst0_t - RxChidTable0AInst0_t;
                tbl_id += step_2 * (inst_cycle/2);

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_inst_chid));

                for (i = 0; i < 2; i++)
                {
                    step_f = RxChidTable0AInst0_cycle1Chid_f - RxChidTable0AInst0_cycle0Chid_f;
                    fld_id = RxChidTable0AInst0_cycle0Chid_f + step_f*i;
                    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_arr[i], &rx_inst_chid);
                }

                /* step2: sync to backup */
                tbl_id = RxChidTable0BInst0_t;
                step_t = RxChidTable0BInst1_t - RxChidTable0BInst0_t;
                tbl_id += step_t * ins_id;
                step_2 = RxChidTable1BInst0_t - RxChidTable0BInst0_t;
                tbl_id += step_2 * (inst_cycle/2);

                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_inst_chid));

                for (i = 0; i < 2; i++)
                {
                    step_f = RxChidTable0BInst0_cycle1Chid_f - RxChidTable0BInst0_cycle0Chid_f;
                    fld_id = RxChidTable0BInst0_cycle0Chid_f + step_f*i;
                    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32_arr[i], &rx_inst_chid, flexe_shim_id, 0);
                }

                /* #3, write HW table*/
                cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_inst_chid));
                /********************* RxChidTable0BInst0 end! ***********************/
            }
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_inst_sch_config(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, uint8 group_inst_offset)
{
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 step_t   = 0;
    uint32 step_f   = 0;
    uint32 factor_t = 0;
    uint32 factor_f = 0;
    uint32 step_2 = 0;
    uint32 factor_2 = 0;
    uint32 val32  = 0;
    int8   i = 0;
    uint8 cycle = 0;
    uint8 asic_inst = 0;
    sys_flexe_group_dir_t *p_group_dir = NULL;

    TxSch0AInst0_m              inst_sch;
    TxChannelIdTable0AInst0_m   inst_chid;

    //SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, group %d dir %s inst sch config\n", __FUNCTION__, __LINE__, \
        group_node->group_id, dir?"TX":"RX");

    /********************************************************************************************
     -- tx mask
       * TxSch[0..79][A-B]Inst[0..7].subcalMask[0..9]

     -- tx channel config
       * TxChannelIdTable[0..39][A-B]Inst[0..7].cycle[0..79]Chid

     -- rx mask
       * RxSch[0..79][A-B]Inst[0..7].subcalMask[0..9]

     -- rx channel config
       * RxChidTable[0..39][A-B]Inst[0..7].cycle[0..79]Chid
    *********************************************************************************************/

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    asic_inst = group_node->inst_list[group_inst_offset];

    /* #1, calc index */
    index = DRV_INS(group_node->flexe_shim_id, 0);

    /* every time instance schedule must be all re-configed */
    for (cycle = 0; cycle < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); cycle++)
    {
        /********************* TxSch0AInst0 start! ***********************/
        /* ##2. calc table step */
        if (SYS_FLEXE_DIR_TX == dir)
        {
            tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? TxSch0AInst0_t : TxSch0BInst0_t;
        }
        else
        {
            tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? RxSch0AInst0_t : RxSch0BInst0_t;
        }

        step_t = TxSch1AInst0_t - TxSch0AInst0_t;
        tbl_id += step_t * cycle;

        step_2 = TxSch0AInst1_t - TxSch0AInst0_t;
        tbl_id += step_2 * asic_inst;

        /* #2.1, read HW table */
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &inst_sch));

        for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); i++)
        {
            step_f = TxSch0AInst0_subcalMask1_f - TxSch0AInst0_subcalMask0_f;
            fld_id = step_f * i;
            val32 = (p_group_dir->ic[group_inst_offset][cycle].ic_subcalmask >> i) & 0x1;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &inst_sch, group_node->flexe_shim_id, 0);
        }

        /* #3, write HW table */
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &inst_sch));
        /********************* TxSch0AInst0 start! ***********************/

        /********************* TxChannelIdTable0BInst0 start! ***********************/
        if (SYS_FLEXE_DIR_TX == dir)
        {
            tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? TxChannelIdTable0AInst0_t : TxChannelIdTable0BInst0_t;
        }
        else
        {
            tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? RxChidTable0AInst0_t : RxChidTable0BInst0_t;
        }

        /* ##2. calc table step 1, get inst step */
        step_t = TxChannelIdTable0AInst1_t - TxChannelIdTable0AInst0_t;
        factor_t = asic_inst;
        tbl_id += step_t*factor_t;

        /* ##2. calc table step 2, get cycle step */
        step_2 = TxChannelIdTable1AInst0_t - TxChannelIdTable0AInst0_t;
        factor_2 = cycle/2;
        tbl_id += step_2*factor_2;

        /* #2.1, read HW table */
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &inst_chid));

        /* ##2.2. calc step */
        step_f = TxChannelIdTable0BInst0_cycle1Chid_f - TxChannelIdTable0BInst0_cycle0Chid_f;
        factor_f = cycle%2; /* even cycle: cycle0Chid;   odd cycle: cycle1Chid */
        /* ##2.3. modify field value */
        fld_id = TxChannelIdTable0BInst0_cycle0Chid_f + step_f*factor_f;
        val32 = p_group_dir->ic[group_inst_offset][cycle].shim_chid;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &inst_chid, group_node->flexe_shim_id, 0);

        /* #3, write HW table*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &inst_chid));
        /********************* TxChannelIdTable0BInst0 end! ***********************/
    }
 
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_inst_bmp_sync(uint8 lchip, uint8 flexe_shim_id, uint8 curr_A_or_B, uint32 inst_mask, sys_flexe_dir_t dir)
{
    uint32 index  = 0;
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 val32_curr  = 0;
    uint32 val32_back  = 0;
    uint32 val32  = 0;

    TxClientSchEnA_m          tx_client_sch_en;
    RxClientSchEnA_m          rx_client_sch_en;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, shim %d dir %s sync inst bmp config\n", __FUNCTION__, __LINE__, \
        flexe_shim_id, dir?"TX":"RX");

    index = DRV_INS(flexe_shim_id, 0);

    if (SYS_FLEXE_DIR_TX == dir)
    {
        if (SYS_FLEXE_ACTIVE_B == curr_A_or_B)  /* B -> A */
        {
            FLEXE_DBG_PRINTF("B->A, TX!\n");
            /********************* TxClientSchEnB start! ***********************/
            tbl_id = TxClientSchEnB_t;
            /* #2.1, read HW table */
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_client_sch_en));
            fld_id = TxClientSchEnB_cfgTxInstEnBmp_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_curr, &tx_client_sch_en);
            FLEXE_DBG_PRINTF("inst_mask = 0x%x\n", inst_mask);
            FLEXE_DBG_PRINTF("val32_curr = 0x%x\n", val32_curr);

            tbl_id = TxClientSchEnA_t;
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_client_sch_en));

            fld_id = TxClientSchEnA_cfgTxInstEnBmp_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_back, &tx_client_sch_en);
            FLEXE_DBG_PRINTF("val32_back = 0x%x\n", val32_back);

            val32 = (val32_back & (~inst_mask)) | (val32_curr & (inst_mask));
            FLEXE_DBG_PRINTF("val32_write = 0x%x\n", val32);

            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &tx_client_sch_en, flexe_shim_id, 0);

            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_client_sch_en));
            /********************* TxClientSchEnB end! ***********************/
        }
        else  /* A -> B */
        {
            FLEXE_DBG_PRINTF("A->B, TX!\n");
            /********************* TxClientSchEnA start! ***********************/
            tbl_id = TxClientSchEnA_t;
            /* #2.1, read HW table */
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_client_sch_en));
            fld_id = TxClientSchEnA_cfgTxInstEnBmp_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_curr, &tx_client_sch_en);
            FLEXE_DBG_PRINTF("inst_mask = 0x%x\n", inst_mask);
            FLEXE_DBG_PRINTF("val32_curr = 0x%x\n", val32_curr);

            tbl_id = TxClientSchEnB_t;
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_client_sch_en));

            fld_id = TxClientSchEnB_cfgTxInstEnBmp_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_back, &tx_client_sch_en);
            FLEXE_DBG_PRINTF("val32_back = 0x%x\n", val32_back);

            val32 = (val32_back & (~inst_mask)) | (val32_curr & (inst_mask));
            FLEXE_DBG_PRINTF("val32_write = 0x%x\n", val32);

            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &tx_client_sch_en, flexe_shim_id, 0);

            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_client_sch_en));
            /********************* TxClientSchEnA end! ***********************/
        }
    }
    else
    {
        if (SYS_FLEXE_ACTIVE_B == curr_A_or_B)  /* B -> A */
        {
            FLEXE_DBG_PRINTF("B->A, RX!\n");
            /********************* RxClientSchEnB start! ***********************/
            tbl_id = RxClientSchEnB_t;
            /* #2.1, read HW table */
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_client_sch_en));
            fld_id = RxClientSchEnB_cfgRxInstEnBmp_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_curr, &rx_client_sch_en);
            FLEXE_DBG_PRINTF("inst_mask = 0x%x\n", inst_mask);
            FLEXE_DBG_PRINTF("val32_curr = 0x%x\n", val32_curr);

            tbl_id = RxClientSchEnA_t;
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_client_sch_en));

            fld_id = RxClientSchEnA_cfgRxInstEnBmp_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_back, &rx_client_sch_en);
            FLEXE_DBG_PRINTF("val32_back = 0x%x\n", val32_back);

            val32 = (val32_back & (~inst_mask)) | (val32_curr & (inst_mask));
            FLEXE_DBG_PRINTF("val32_write = 0x%x\n", val32);

            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &rx_client_sch_en, flexe_shim_id, 0);

            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_client_sch_en));
            /********************* RxClientSchEnB end! ***********************/
        }
        else  /* A -> B */
        {
            FLEXE_DBG_PRINTF("A->B, RX!\n");
            /********************* RxClientSchEnA start! ***********************/
            tbl_id = RxClientSchEnA_t;
            /* #2.1, read HW table */
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_client_sch_en));
            fld_id = RxClientSchEnA_cfgRxInstEnBmp_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_curr, &rx_client_sch_en);
            FLEXE_DBG_PRINTF("inst_mask = 0x%x\n", inst_mask);
            FLEXE_DBG_PRINTF("val32_curr = 0x%x\n", val32_curr);

            tbl_id = RxClientSchEnB_t;
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_client_sch_en));

            fld_id = RxClientSchEnB_cfgRxInstEnBmp_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32_back, &rx_client_sch_en);
            FLEXE_DBG_PRINTF("val32_back = 0x%x\n", val32_back);

            val32 = (val32_back & (~inst_mask)) | (val32_curr & (inst_mask));
            FLEXE_DBG_PRINTF("val32_write = 0x%x\n", val32);

            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &rx_client_sch_en, flexe_shim_id, 0);

            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_client_sch_en));
            /********************* RxClientSchEnA end! ***********************/
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_inst_subcal_sync(uint8 lchip, uint8 flexe_shim_id, uint8 curr_A_or_B, uint8 ins_id, sys_flexe_dir_t dir)
{
    uint32 index  = 0;
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 step_t = 0;
    uint32 cmd    = 0;
    uint32 val32  = 0;

    TxSubcalendarEnAInst0_m   tx_subcal_en;
    RxSubcalendarEnAInst0_m   rx_subcal_en;

    //SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, shim %d inst %d dir %s sync inst subcal config\n", __FUNCTION__, __LINE__, \
        flexe_shim_id, ins_id, dir?"TX":"RX");

    index = DRV_INS(flexe_shim_id, 0);

    if (SYS_FLEXE_DIR_TX == dir)
    {
        if (SYS_FLEXE_ACTIVE_B == curr_A_or_B)  /* B -> A */
        {
            /********************* TxSubcalendarEnBInst0 start! ***********************/
            /* step1: get active value */
            tbl_id = TxSubcalendarEnBInst0_t;
            step_t = TxSubcalendarEnBInst1_t - TxSubcalendarEnBInst0_t;
            tbl_id += step_t * ins_id;

            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_subcal_en));

            fld_id = TxSubcalendarEnBInst0_perSubcalEnable_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &tx_subcal_en);

            /* step2: sync to backup */
            tbl_id = TxSubcalendarEnAInst0_t;
            step_t = TxSubcalendarEnAInst1_t - TxSubcalendarEnAInst0_t;
            tbl_id += step_t * ins_id;

            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_subcal_en));

            fld_id = TxSubcalendarEnAInst0_perSubcalEnable_f;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &tx_subcal_en, flexe_shim_id, 0);

            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_subcal_en));
            /********************* TxSubcalendarEnBInst0 end! ***********************/
        }
        else   /* A -> B */
        {
            /********************* TxSubcalendarEnAInst0 start! ***********************/
            /* step1: get active value */
            tbl_id = TxSubcalendarEnAInst0_t;
            step_t = TxSubcalendarEnAInst1_t - TxSubcalendarEnAInst0_t;
            tbl_id += step_t * ins_id;

            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_subcal_en));

            fld_id = TxSubcalendarEnAInst0_perSubcalEnable_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &tx_subcal_en);

            /* step2: sync to backup */
            tbl_id = TxSubcalendarEnBInst0_t;
            step_t = TxSubcalendarEnBInst1_t - TxSubcalendarEnBInst0_t;
            tbl_id += step_t * ins_id;

            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_subcal_en));

            fld_id = TxSubcalendarEnBInst0_perSubcalEnable_f;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &tx_subcal_en, flexe_shim_id, 0);

            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &tx_subcal_en));
            /********************* TxSubcalendarEnAInst0 end! ***********************/
        }
    }
    else   /* RX */
    {
        if (SYS_FLEXE_ACTIVE_B == curr_A_or_B)  /* B -> A */
        {
            /********************* RxSubcalendarEnBInst0 start! ***********************/
            /* step1: get active value */
            tbl_id = RxSubcalendarEnBInst0_t;
            step_t = RxSubcalendarEnBInst1_t - RxSubcalendarEnBInst0_t;
            tbl_id += step_t * ins_id;

            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_subcal_en));

            fld_id = RxSubcalendarEnBInst0_perSubcalEnable_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &rx_subcal_en);

            /* step2: sync to backup */
            tbl_id = RxSubcalendarEnAInst0_t;
            step_t = RxSubcalendarEnAInst1_t - RxSubcalendarEnAInst0_t;
            tbl_id += step_t * ins_id;

            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_subcal_en));

            fld_id = RxSubcalendarEnAInst0_perSubcalEnable_f;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &rx_subcal_en, flexe_shim_id, 0);

            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_subcal_en));
            /********************* RxSubcalendarEnBInst0 end! ***********************/
        }
        else   /* A -> B */
        {
            /********************* RxSubcalendarEnAInst0 start! ***********************/
            /* step1: get active value */
            tbl_id = RxSubcalendarEnAInst0_t;
            step_t = RxSubcalendarEnAInst1_t - RxSubcalendarEnAInst0_t;
            tbl_id += step_t * ins_id;

            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_subcal_en));

            fld_id = RxSubcalendarEnAInst0_perSubcalEnable_f;
            DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &rx_subcal_en);

            /* step2: sync to backup */
            tbl_id = RxSubcalendarEnBInst0_t;
            step_t = RxSubcalendarEnBInst1_t - RxSubcalendarEnBInst0_t;
            tbl_id += step_t * ins_id;

            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_subcal_en));

            fld_id = RxSubcalendarEnBInst0_perSubcalEnable_f;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &rx_subcal_en, flexe_shim_id, 0);

            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_subcal_en));
            /********************* TxSubcalendarEnAInst0 end! ***********************/
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_client_en(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir)
{
    uint32 tbl_id = 0;
    uint32 tbl_base = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;
    uint32 step   = 0;
    uint32 factor = 0;
    int8  i = 0, j = 0;
    uint8 asic_inst = 0;
    uint8 inst_used[SYS_FLEXE_MAX_INST_CNT] = {0};

    sys_flexe_group_dir_t *p_group_dir = NULL;

    TxClientSchEnA_m          client_sch_en;
    TxSubcalendarEnAInst0_m   subcal_en;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, group %d dir %s set client en\n", __FUNCTION__, __LINE__, \
        group_node->group_id, dir?"TX":"RX");

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    /********************************************************************************************
     -- enable bitmap
      * TxClientSchEnA.cfgTxInstEnBmp
      * TxClientSchEnB.cfgTxInstEnBmp
      * RxClientSchEnA.cfgRxInstEnBmp
      * RxClientSchEnB.cfgRxInstEnBmp
      * 
      * TxSubcalendarEn[A-B]Inst[0..7].perSubcalEnable
      * RxSubcalendarEn[A-B]Inst[0..7].perSubcalEnable
    *********************************************************************************************/

    /*************** TxClientSchEnB start! ****************/
    /* #1, calc index */
    index = DRV_INS(group_node->flexe_shim_id, 0);

    /* #2, read HW table */
    if (SYS_FLEXE_DIR_TX == dir)
    {
        tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? TxClientSchEnA_t : TxClientSchEnB_t;
    }
    else
    {
        tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? RxClientSchEnA_t : RxClientSchEnB_t;
    }
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &client_sch_en));

    /* ##2.2. modify field value */
    /* ###2.2.1. */
    fld_id = TxClientSchEnB_cfgTxInstEnBmp_f;
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &client_sch_en);

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        asic_inst = group_node->inst_list[i];
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            if (SYS_FLEXE_ACTIVE_A == p_group_dir->active)
            {
                if (p_group_dir->dir_inst[i].switch_shim_chid_b[j])
                {
                    inst_used[asic_inst] = 1;   //fix,add
                }
            }
            else
            {
                if (p_group_dir->dir_inst[i].switch_shim_chid_a[j])
                {
                    inst_used[asic_inst] = 1;   //fix,add
                }
            }
        }
    }
 
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        asic_inst = group_node->inst_list[i];
        if (1 == inst_used[asic_inst])
        {
            val32 |= (1 << asic_inst);
        }
        else if (0 == inst_used[asic_inst])
        {
            val32 &= ~(1 << asic_inst);
        }
    }
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &client_sch_en, group_node->flexe_shim_id, 0);

    /* #3, write HW table*/
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &client_sch_en));
    /*************** TxClientSchEnB end! ****************/

    /*************** TxSubcalendarEnBInst0 start! ****************/
    /* #1, calc index */
    index = DRV_INS(group_node->flexe_shim_id, 0);

    if (SYS_FLEXE_DIR_TX == dir)
    {
        tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? TxSubcalendarEnAInst0_t : TxSubcalendarEnBInst0_t;
    }
    else
    {
        tbl_id = (SYS_FLEXE_ACTIVE_B == p_group_dir->active) ? RxSubcalendarEnAInst0_t : RxSubcalendarEnBInst0_t;
    }
    tbl_base = tbl_id;

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        asic_inst = group_node->inst_list[i];
        SYS_CONDITION_CONTINUE(0 == inst_used[asic_inst]);

        /* #2, read HW table */
        step = TxSubcalendarEnBInst1_t - TxSubcalendarEnBInst0_t;
        factor = asic_inst;
        tbl_id = tbl_base;
        tbl_id += step*factor;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &subcal_en));
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &subcal_en);

        /* ##2.2. modify field value */
        /* ###2.2.1. */
        fld_id = TxSubcalendarEnBInst0_perSubcalEnable_f;

        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            if (SYS_FLEXE_ACTIVE_A == p_group_dir->active)
            {
                if (0 == p_group_dir->dir_inst[i].switch_shim_chid_b[j])
                {
                    val32 &= ~(1 << j);
                }
                else
                {
                    val32 |= (1 << j);
                }
            }
            else
            {
                if (0 == p_group_dir->dir_inst[i].switch_shim_chid_a[j])
                {
                    val32 &= ~(1 << j);
                }
                else
                {
                    val32 |= (1 << j);
                }

            }
        }

        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &subcal_en, group_node->flexe_shim_id, 0);

        /* #3, write HW table*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &subcal_en));
    }

    /*************** TxSubcalendarEnBInst0 end! ****************/

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_sch_config(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 slot_shu = 0;
    uint8 slot_heng = 0;
    uint8 cycle_value = 0;
    uint8 asic_inst = 0;
    uint8 inst_used[SYS_FLEXE_MAX_INST_CNT] = {0};
    sys_flexe_group_dir_t *p_group_dir = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    /* client sch cleaer */
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "_sys_tmm_flexe_client_sch_config_clear\n");
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            asic_inst = group_node->inst_list[i];
            slot_shu = asic_inst*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) + j;
            (void)_sys_tmm_flexe_slot_shu2heng(lchip, group_node, slot_shu, &slot_heng);
            cycle_value = SYS_TMM_FLEXE_GET_CLIENT_CYCLE(slot_heng);
            CTC_ERROR_RETURN(_sys_tmm_flexe_client_sch_config_clear(lchip, group_node, cycle_value, dir));
        }
    }
    /* client sch */
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "_sys_tmm_flexe_client_sch_config\n");
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            asic_inst = group_node->inst_list[i];
            slot_shu = asic_inst*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) + j;
            (void)_sys_tmm_flexe_slot_shu2heng(lchip, group_node, slot_shu, &slot_heng);
            cycle_value = SYS_TMM_FLEXE_GET_CLIENT_CYCLE(slot_heng);
            CTC_ERROR_RETURN(_sys_tmm_flexe_client_sch_config(lchip, group_node, cycle_value, dir));
        }
    }

    /* calc used inst */
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "_sys_tmm_flexe_inst_sch_config\n");
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            if (SYS_FLEXE_ACTIVE_A == p_group_dir->active)
            {
                if (p_group_dir->dir_inst[i].switch_shim_chid_b[j])
                {
                    inst_used[i] = 1;   //fix,add
                }
                if ((p_group_dir->dir_inst[i].switch_shim_chid_b[j] == 0) && p_group_dir->dir_inst[i].switch_shim_chid_a[j])
                {
                    inst_used[i] = 1;   //remove
                }
            }
            else
            {
                if (p_group_dir->dir_inst[i].switch_shim_chid_a[j])
                {
                    inst_used[i] = 1;   //fix,add
                }
                if ((p_group_dir->dir_inst[i].switch_shim_chid_a[j] == 0) && p_group_dir->dir_inst[i].switch_shim_chid_b[j])
                {
                    inst_used[i] = 1;   //remove
                }
            }
        }
    }
    /* inst sch */
    for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); j++)
    {
        if (inst_used[j])
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_inst_sch_config(lchip, group_node, dir, j));
        }
    }

    /* set client en */
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_client_en(lchip, group_node, dir));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_flush_config(uint8 lchip, sys_flexe_group_t* group_node, uint8 dir)
{
    uint8 i = 0;
    uint8 asic_inst = 0;
    sys_flexe_group_dir_t *p_group_dir = NULL;

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, set group %d flush config\n", __FUNCTION__, __LINE__, group_node->group_id);

    for(i = 0; i < group_node->inst_cnt; i++)
    {
        asic_inst = group_node->inst_list[i];

        /* Step1: clear flush(register) */
        CTC_ERROR_RETURN(_sys_tmm_flexe_subcal_flush_cfg(lchip, group_node->flexe_shim_id, asic_inst, dir, 0x0));

        /* Step2: group flush */
        CTC_ERROR_RETURN(_sys_tmm_flexe_subcal_flush_cfg(lchip, group_node->flexe_shim_id, asic_inst, dir, p_group_dir->dir_inst[i].flush_bmp));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_flush_config_clear(uint8 lchip, sys_flexe_group_t* group_node, uint8 dir)
{
    uint8 i = 0;
    uint8 asic_inst = 0;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, set group %d flush config\n", __FUNCTION__, __LINE__, group_node->group_id);

    for(i = 0; i < group_node->inst_cnt; i++)
    {
        asic_inst = group_node->inst_list[i];

        CTC_ERROR_RETURN(_sys_tmm_flexe_subcal_flush_cfg(lchip, group_node->flexe_shim_id, asic_inst, dir, 0x0));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_cross_config(uint8 lchip, sys_flexe_client_t* client_node, sys_flexe_dir_t dir, sys_flexe_client_calcfg_t* flexe_client_cal)
{
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, set client %d cross config\n", __FUNCTION__, __LINE__, client_node->client_id);

    if (SYS_FLEXE_DIR_TX == dir)
    {
        if (SYS_FLEXE_CLIENT_ADD == client_node->tx.op)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_fifo_read_cfg(lchip, client_node, TRUE));
            CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp(lchip, client_node, SYS_FLEXE_FLOW_TYPE_B, TRUE));
            CTC_ERROR_RETURN(_sys_tmm_flexe_fifo_full_thrd(lchip, client_node, TRUE));

            CTC_ERROR_RETURN(_sys_tmm_flexe_cross_map_config(lchip, client_node, SYS_FLEXE_DIR_TX, TRUE));
            CTC_ERROR_RETURN(_sys_tmm_flexe_cross_cal_config(lchip, client_node->flexe_shim_id, flexe_client_cal));

            CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_writemask(lchip, client_node->flexe_shim_id, client_node->tx_xc_chid, SYS_FLEXE_FLOW_TYPE_B, TRUE));
        }
        else if (SYS_FLEXE_CLIENT_REMOVE == client_node->tx.op)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_cross_map_config(lchip, client_node, SYS_FLEXE_DIR_TX, FALSE));
            CTC_ERROR_RETURN(_sys_tmm_flexe_cross_cal_config(lchip, client_node->flexe_shim_id, flexe_client_cal));

            CTC_ERROR_RETURN(_sys_tmm_flexe_fifo_read_cfg(lchip, client_node, FALSE));
            CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp(lchip, client_node, SYS_FLEXE_FLOW_TYPE_B, FALSE));
            CTC_ERROR_RETURN(_sys_tmm_flexe_fifo_full_thrd(lchip, client_node, FALSE));

            CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_writemask(lchip, client_node->flexe_shim_id, client_node->tx_xc_chid, SYS_FLEXE_FLOW_TYPE_B, FALSE));

        }
        else if (SYS_FLEXE_CLIENT_RESIZE == client_node->tx.op)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_writemask(lchip, client_node->flexe_shim_id, client_node->tx_xc_chid, SYS_FLEXE_FLOW_TYPE_B, FALSE));

            CTC_ERROR_RETURN(_sys_tmm_flexe_fifo_read_cfg(lchip, client_node, TRUE));
            CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp(lchip, client_node, SYS_FLEXE_FLOW_TYPE_B, TRUE));
            CTC_ERROR_RETURN(_sys_tmm_flexe_fifo_full_thrd(lchip, client_node, TRUE));

            CTC_ERROR_RETURN(_sys_tmm_flexe_cross_map_config(lchip, client_node, SYS_FLEXE_DIR_TX, TRUE));
            CTC_ERROR_RETURN(_sys_tmm_flexe_cross_cal_config(lchip, client_node->flexe_shim_id, flexe_client_cal));

            CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_writemask(lchip, client_node->flexe_shim_id, client_node->tx_xc_chid, SYS_FLEXE_FLOW_TYPE_B, TRUE));
        }
    }
    else
    {
        if (SYS_FLEXE_CLIENT_ADD == client_node->rx.op)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_macrx_cal_config(lchip, client_node->flexe_shim_id, flexe_client_cal));
            CTC_ERROR_RETURN(_sys_tmm_flexe_cross_map_config(lchip, client_node, SYS_FLEXE_DIR_RX, TRUE));
            CTC_ERROR_RETURN(_sys_tmm_flexe_mcfifo_writemask(lchip, client_node->flexe_shim_id, client_node->tx_xc_chid, TRUE));
        }
        else if (SYS_FLEXE_CLIENT_REMOVE == client_node->rx.op)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_cross_map_config(lchip, client_node, SYS_FLEXE_DIR_RX, FALSE));
            CTC_ERROR_RETURN(_sys_tmm_flexe_macrx_cal_config(lchip, client_node->flexe_shim_id, flexe_client_cal));
            CTC_ERROR_RETURN(_sys_tmm_flexe_mcfifo_writemask(lchip, client_node->flexe_shim_id, client_node->tx_xc_chid, FALSE));
        }
        else if (SYS_FLEXE_CLIENT_RESIZE == client_node->rx.op)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_macrx_cal_config(lchip, client_node->flexe_shim_id, flexe_client_cal));
            CTC_ERROR_RETURN(_sys_tmm_flexe_cross_map_config(lchip, client_node, SYS_FLEXE_DIR_RX, TRUE));
            CTC_ERROR_RETURN(_sys_tmm_flexe_mcfifo_writemask(lchip, client_node->flexe_shim_id, client_node->tx_xc_chid, TRUE));
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_mac_config(uint8 lchip, sys_flexe_client_t *client_node, sys_flexe_dir_t dir)
{
    uint8 active_slot_cnt = 0;
    uint32 tbl_id = 0;
    uint8 serdes_mode   = 0;
    uint8 fec_type      = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 step   = 0;
    uint32 factor = 0;
    uint32 val32  = 0;
    uint32 curr_rx_speed = 0;
    uint32 eth_val32    = 0;
    uint8  txqm_id = 0;
    uint8 physical_serdes_id = 0;
    uint32* p_mii_txrxcfg = NULL;
    uint32  size = 0;
    int32   ret  = CTC_E_NONE;
    uint8   mac_rx_buf = 0;
    sys_flexe_client_dir_t *p_client_dir = NULL;
    sys_flexe_group_t *group_node = NULL;

    McMacPcsCfg_m         mac_pcs;
    McMacMacTxCfg_m       mac_mac;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    p_client_dir = (SYS_FLEXE_DIR_TX == dir) ? &client_node->tx : &client_node->rx;

    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n ### %s @ %d, mac_id: %d, op is %d\n", __FUNCTION__, __LINE__, client_node->mac_id, p_client_dir->op);

    _sys_tmm_flexe_group_lookup(lchip, client_node->group_id, &group_node);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group ID %d not exist!\n", client_node->group_id);
        return CTC_E_NOT_EXIST;
    }

    if (SYS_FLEXE_UNUSED_FLAG_U16 == client_node->mac_id)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] Client %d haven't binded mac, won't set mac config\n", client_node->client_id);
        return CTC_E_NONE;
    }

    if (SYS_FLEXE_DIR_TX == dir)
    {
        size = sizeof(McMacMiiTxCfg_m);
    }
    else
    {
        size = sizeof(McMacMiiRxCfg_m);
    }
    p_mii_txrxcfg = (uint32*)mem_malloc(MEM_DMPS_MODULE, size);
    if (!p_mii_txrxcfg)
    {
        return CTC_E_NO_MEMORY;
    }

    sal_memset(p_mii_txrxcfg, 0, size);

    txqm_id = SYS_TMM_GET_TXQM_BY_MACID(client_node->mac_id);
    /*In PHY list of a group,  fec mode and serdes mode is same, only need to care first PHY's fec mode and serdes mode */
    _sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, group_node->phy_list[0].logical_serdes_base, &physical_serdes_id);
    if (SYS_TMM_USELESS_ID8 == physical_serdes_id)
    {
        ret = CTC_E_INVALID_PARAM;
        goto RELEASE_PTR_RETURN;
    }
    CTC_ERROR_GOTO(sys_tmm_serdes_get_glb_info(lchip, physical_serdes_id, SYS_TMM_SERDES_GLB_DATA_RATE, &serdes_mode), ret, RELEASE_PTR_RETURN);
    if(CTC_CHIP_MAX_SERDES_MODE <= serdes_mode)
    {
        ret = CTC_E_INVALID_PARAM;
        goto RELEASE_PTR_RETURN;
    }
    CTC_ERROR_GOTO(sys_tmm_serdes_get_glb_info(lchip, physical_serdes_id, SYS_TMM_SERDES_GLB_FEC_TYPE, &fec_type), ret, RELEASE_PTR_RETURN);
    if(CTC_PORT_FEC_TYPE_MAX <= fec_type)
    {
        ret = CTC_E_INVALID_PARAM;
        goto RELEASE_PTR_RETURN;
    }

    /* calc current speed */
    _sys_tmm_flexe_get_client_speed_val(lchip, client_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_INACTIVE_FLAG, &curr_rx_speed);

    if (SYS_FLEXE_DIR_TX == dir)
    {
        /*************** (II) McMacMiiTxCfg start! ****************/
        /* #1, calc index */
        index = DRV_INS(txqm_id, 0);

        /* #2, read HW table: McMacMiiTxCfg */
        tbl_id = McMacMiiTxCfg_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd, p_mii_txrxcfg), ret, RELEASE_PTR_RETURN);

        /* ##2.1. calc step */
        step = McMacMiiTxCfg_cfgMcMacMiiTx_1_cfgMcMacTxSpeed_f - McMacMiiTxCfg_cfgMcMacMiiTx_0_cfgMcMacTxSpeed_f;

        factor = SYS_TMM_GET_MACID_PER_TXQM(client_node->mac_id);

        /* ##2.2. modify field value */
        /* ###2.2.1. */
        fld_id = McMacMiiTxCfg_cfgMcMacMiiTx_0_cfgMcMacTxSpeed_f + step*factor;
        /* For FlexE mode, this value will be a const */
        eth_val32 = _sys_tmm_flexe_mac_get_eth_config_val(lchip, serdes_mode, fec_type, McMac_cfgMcMacTxSpeed);
        val32 = (SYS_FLEXE_CLIENT_REMOVE == p_client_dir->op) ? eth_val32 : 8;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, p_mii_txrxcfg, txqm_id, 0);

        fld_id = McMacMiiTxCfg_cfgMcMacMiiTx_0_cfgMcMacTxAmInterval_f + step*factor;
        eth_val32 = _sys_tmm_flexe_mac_get_eth_config_val(lchip, serdes_mode, fec_type, McMac_cfgTxAmInterval);
        val32 = (SYS_FLEXE_CLIENT_REMOVE == p_client_dir->op) ? eth_val32 : 1138;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, p_mii_txrxcfg, txqm_id, 0);

        fld_id = McMacMiiTxCfg_cfgMcMacMiiTx_0_cfgMcMacTxIpgDelEn_f + step*factor;
        val32 = 0x1;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, p_mii_txrxcfg, txqm_id, 0);

        fld_id = McMacMiiTxCfg_cfgMcMacMiiTx_0_cfgMcMacTxFlexEIpgDelCnt_f + step*factor;
        val32 =  (SYS_FLEXE_CLIENT_REMOVE == p_client_dir->op) ? 0 : 1;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, p_mii_txrxcfg, txqm_id, 0);

        /* #3, write HW table: McMacMiiTxCfg*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd, p_mii_txrxcfg), ret, RELEASE_PTR_RETURN);
        /*************** (II) McMacMiiTxCfg end! ****************/

        /*************** (III) McMacPcsCfg start! ****************/
        /* #1, calc index */
        index = DRV_INS(txqm_id, 0);

        /* #2, read HW table: McMacMiiTxCfg */
        tbl_id = McMacPcsCfg_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd, &mac_pcs), ret, RELEASE_PTR_RETURN);

        /* ##2.1. calc step */
        step = McMacPcsCfg_mcMacPcsCfg_1_cfgMcMacPcsSyncStatusDisable_f - McMacPcsCfg_mcMacPcsCfg_0_cfgMcMacPcsSyncStatusDisable_f;
        factor = SYS_TMM_GET_MACID_PER_TXQM(client_node->mac_id);

        /* ##2.2. modify field value */
        /* ###2.2.1. */
        fld_id = McMacPcsCfg_mcMacPcsCfg_0_cfgMcMacPcsSyncStatusDisable_f + step*factor;
        val32 = (SYS_FLEXE_CLIENT_REMOVE == p_client_dir->op) ? 0 : 1;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mac_pcs, txqm_id, 0);

        /* #3, write HW table: McMacMiiTxCfg*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd, &mac_pcs), ret, RELEASE_PTR_RETURN);
        /*************** (III) McMacPcsCfg end! ****************/

        /*************** (III) McMacMacTxCfg start! ****************/
        /* #1, calc index */
        index = DRV_INS(txqm_id, 0);

        /* #2, read HW table: cfgMcMacTxWaitCaptureTs */
        tbl_id = McMacMacTxCfg_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd, &mac_mac), ret, RELEASE_PTR_RETURN);

        /* ##2.1. calc step */
        step = McMacMacTxCfg_cfgMcMacMacTx_1_cfgMcMacTxWaitCaptureTs_f - McMacMacTxCfg_cfgMcMacMacTx_0_cfgMcMacTxWaitCaptureTs_f;
        factor = SYS_TMM_GET_MACID_PER_TXQM(client_node->mac_id);

        /* ##2.2. modify field value */
        /* ###2.2.1. */
        fld_id = McMacMacTxCfg_cfgMcMacMacTx_0_cfgMcMacTxWaitCaptureTs_f + step*factor;
        val32 = (SYS_FLEXE_CLIENT_REMOVE == p_client_dir->op) ? 1 : 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mac_mac, txqm_id, 0);

        /* #3, write HW table: cfgMcMacTxWaitCaptureTs*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd, &mac_mac), ret, RELEASE_PTR_RETURN);
        /*************** (III) McMacMacTxCfg end! ****************/
    }
    else  /* RX */
    {
        /*************** (II) McMacMiiRxCfg start! ****************/
        /* #1, calc index */
        index = DRV_INS(txqm_id, 0);

        /* #2, read HW table: McMacMiiRxCfg */
        tbl_id = McMacMiiRxCfg_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd, p_mii_txrxcfg), ret, RELEASE_PTR_RETURN);

        /* ##2.1. calc step */
        step = McMacMiiRxCfg_cfgMcMacMiiRx_1_cfgMcMacMiiRxFaultMaskLinkEn_f - McMacMiiRxCfg_cfgMcMacMiiRx_0_cfgMcMacMiiRxFaultMaskLinkEn_f;
        factor = SYS_TMM_GET_MACID_PER_TXQM(client_node->mac_id);
        /* ##2.2. modify field value */
        /* ###2.2.1. */
        fld_id = McMacMiiRxCfg_cfgMcMacMiiRx_0_cfgMcMacMiiRxFaultMaskLinkEn_f + step*factor;
        _sys_tmm_flexe_get_client_slot_cnt(lchip, client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_ACTIVE_FLAG, &active_slot_cnt);
        val32 = ((!active_slot_cnt) && (SYS_FLEXE_CLIENT_REMOVE == p_client_dir->op)) ? 0 : 1;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, p_mii_txrxcfg, txqm_id, 0);

        fld_id = McMacMiiRxCfg_cfgMcMacMiiRx_0_cfgMcMacMiiSgmiiMod_f + step*factor;
        eth_val32 = _sys_tmm_flexe_mac_get_eth_config_val(lchip, serdes_mode, fec_type, McMac_cfgMcMacMiiSgmiiMod);
        val32 = (SYS_FLEXE_CLIENT_REMOVE == p_client_dir->op) ? eth_val32 : 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, p_mii_txrxcfg, txqm_id, 0);

        fld_id = McMacMiiRxCfg_cfgMcMacMiiRx_0_cfgMcMacMiiQsgmiiMod_f + step*factor;
        eth_val32 = _sys_tmm_flexe_mac_get_eth_config_val(lchip, serdes_mode, fec_type, McMac_cfgMcMacMiiQsgmiiMod);
        val32 = (SYS_FLEXE_CLIENT_REMOVE == p_client_dir->op) ? eth_val32 : 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, p_mii_txrxcfg, txqm_id, 0);

        fld_id = McMacMiiRxCfg_cfgMcMacMiiRx_0_cfgMcMacMiiRxBuffMaxDepth_f + step*factor;
        eth_val32 = _sys_tmm_flexe_mac_get_eth_config_val(lchip, serdes_mode, fec_type, McMac_cfgMcMacMiiRxBuffMaxDepth);
        SYS_FLEXE_MAC_RX_BUF(curr_rx_speed, mac_rx_buf);
        val32 = (SYS_FLEXE_CLIENT_REMOVE == p_client_dir->op) ? eth_val32 : mac_rx_buf;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, p_mii_txrxcfg, txqm_id, 0);

        /* #3, write HW table: McMacMiiRxCfg*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd, p_mii_txrxcfg), ret, RELEASE_PTR_RETURN);
        /*************** (II) McMacMiiRxCfg end! ****************/
    }

RELEASE_PTR_RETURN:
    if (p_mii_txrxcfg)
    {
        mem_free(p_mii_txrxcfg);
    }
    return ret;
}

STATIC int32
_sys_tmm_flexe_client_aps_en(uint8 lchip, uint16 w_mac, uint16 p_mac, uint8 enable)
{
    uint32  index      = 0;
    uint32  cmd        = 0;
    uint32  fld_id     = 0;
    uint32  step       = 0;
    uint32  factor     = 0;
    uint8   dp_id      = 0;
    uint32  val_u32    = 0;
    DsNetRxPriorityChannelRemap0_m  remap;
    DsNetTxReplicatePortCtl_m aps_port_ctl;
    NetRxPortApsEnCtl_m aps_en_ctl;
    uint32 array32[2] = {0};

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    dp_id = SYS_TMM_GET_DP_ID_FROM_MACID(p_mac);
    index = DRV_INS(dp_id, 0);
    cmd = DRV_IOR(NetRxPortApsEnCtl_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &aps_en_ctl);
    step = NetRxPortApsEnCtl_portApsEn1_f - NetRxPortApsEnCtl_portApsEn0_f;
    factor = SYS_TMM_GET_MACID_PER_DP(p_mac) / SYS_TMM_MAX_MAC_NUM_PER_TXQM;
    fld_id = NetRxPortApsEnCtl_portApsEn0_f + step*factor;
    DRV_IOR_FIELD(lchip, NetRxPortApsEnCtl_t, fld_id, array32, &aps_en_ctl);
    if (enable)
    {
        CTC_BMP_SET(array32, (p_mac % SYS_TMM_MAX_MAC_NUM_PER_TXQM));
    }
    else
    {
        CTC_BMP_UNSET(array32, (p_mac % SYS_TMM_MAX_MAC_NUM_PER_TXQM));
    }
    DRV_IOW_FIELD_NZ(lchip, NetRxPortApsEnCtl_t, fld_id, array32, &aps_en_ctl, dp_id, 0);
    cmd = DRV_IOW(NetRxPortApsEnCtl_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &aps_en_ctl);

    cmd = DRV_IOR(NetRxWrEnCtl_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &aps_en_ctl);
    step = NetRxWrEnCtl_cfgWrEn1_f - NetRxWrEnCtl_cfgWrEn0_f;
    factor = SYS_TMM_GET_MACID_PER_DP(p_mac) / SYS_TMM_MAX_MAC_NUM_PER_TXQM;
    fld_id = NetRxWrEnCtl_cfgWrEn0_f + step*factor;
    DRV_IOR_FIELD(lchip, NetRxWrEnCtl_t, fld_id, array32, &aps_en_ctl);
    CTC_BMP_UNSET(array32, (p_mac % SYS_TMM_MAX_MAC_NUM_PER_TXQM));
    DRV_IOW_FIELD_NZ(lchip, NetRxWrEnCtl_t, fld_id, array32, &aps_en_ctl, dp_id, 0);
    cmd = DRV_IOW(NetRxWrEnCtl_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &aps_en_ctl);

    index = DRV_INS(dp_id, SYS_TMM_GET_MACID_PER_TXQM(p_mac));
    step = DsNetRxPriorityChannelRemap1_t - DsNetRxPriorityChannelRemap0_t;
    factor = SYS_TMM_GET_MACID_PER_DP(p_mac) / SYS_TMM_MAX_MAC_NUM_PER_TXQM;
    cmd = DRV_IOR(DsNetRxPriorityChannelRemap0_t+step*factor, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &remap);
    fld_id = DsNetRxPriorityChannelRemap0_port_f;
    val_u32 = w_mac % SYS_TMM_MAX_MAC_NUM_PER_TXQM;
    DRV_IOW_FIELD_NZ(lchip, DsNetRxPriorityChannelRemap0_t+step*factor, fld_id, &val_u32, &remap, dp_id, 0);
    cmd = DRV_IOW(DsNetRxPriorityChannelRemap0_t+step*factor, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &remap);

    dp_id = SYS_TMM_GET_DP_ID_FROM_MACID(w_mac);
    index = DRV_INS(dp_id, SYS_TMM_GET_MACID_PER_DP(w_mac));
    cmd = DRV_IOR(DsNetTxReplicatePortCtl_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &aps_port_ctl);
    val_u32 = enable?1:0;
    DRV_IOW_FIELD_NZ(lchip, DsNetTxReplicatePortCtl_t, DsNetTxReplicatePortCtl_cfgRepEn_f,
        &val_u32, &aps_port_ctl, dp_id, 0);
    val_u32 = SYS_TMM_GET_MACID_PER_DP(p_mac);
    DRV_IOW_FIELD_NZ(lchip, DsNetTxReplicatePortCtl_t, DsNetTxReplicatePortCtl_cfgRepPort_f,
        &val_u32, &aps_port_ctl, dp_id, 0);
    cmd = DRV_IOW(DsNetTxReplicatePortCtl_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &aps_port_ctl);

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_set_mcmac_tx_rx_en(uint8 lchip, sys_flexe_client_t** pp_client_node, uint32 tx_rx)
{
    uint8  tx_en  = 0;
    uint8  rx_en  = 0;
    uint8  txqm_id = 0;
    uint16 mac_id = 0;
    uint32 val32  = 0;
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 step   = 0;
    uint32 factor = 0;
    uint32 lport  = 0;
    uint32 array32[2]  = {0};
    sys_flexe_client_t* client_node = *pp_client_node;
    McMacMacTxCfg_m            mac_cfg;
    uint8   dp_id      = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;
    NetRxWrEnCtl_m       aps_en_ctl;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n ### %s @ %d\n", __FUNCTION__, __LINE__);

    lport = CTC_MAP_GPORT_TO_LPORT(client_node->gport);
    if (SYS_FLEXE_UNUSED_FLAG_U16 == lport)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FLEXE] Client %d has not binded lport\n", client_node->client_id );
        return CTC_E_INVALID_PARAM;
    }

    mac_id = client_node->mac_id;
    if (SYS_FLEXE_UNUSED_FLAG_U16 == mac_id)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FLEXE] Client %d has no mac id\n", client_node->client_id );
        return CTC_E_INVALID_PARAM;
    }

    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n ### %s @ %d, lport: %d\n", __FUNCTION__, __LINE__, lport);

    /*************** (I) memset 0 ****************/
    sal_memset(&mac_cfg, 0, sizeof(McMacMacTxCfg_m));

    port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
    if (!port_attr)
    {
        return CTC_E_NO_MEMORY;
    }

    tx_en = tx_rx & 0x1;
    rx_en = tx_rx & 0x2;

    dp_id = SYS_TMM_GET_DP_ID_FROM_CHANID(port_attr->chan_id);
    index = DRV_INS(dp_id, 0);
    cmd = DRV_IOR(NetRxWrEnCtl_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &aps_en_ctl);
    step = NetRxWrEnCtl_cfgWrEn1_f - NetRxWrEnCtl_cfgWrEn0_f;

    if (client_node->aps_role < 2)
    {
        factor = SYS_TMM_GET_MACID_PER_DP(port_attr->mac_id) / SYS_TMM_MAX_MAC_NUM_PER_TXQM;
        fld_id = NetRxWrEnCtl_cfgWrEn0_f + step*factor;
        DRV_IOR_FIELD(lchip, NetRxWrEnCtl_t, fld_id, array32, &aps_en_ctl);

        /* working path */
        if (rx_en)
        {
            CTC_BMP_SET(array32, (port_attr->mac_id % SYS_TMM_MAX_MAC_NUM_PER_TXQM));
        }
        else
        {
            CTC_BMP_UNSET(array32, (port_attr->mac_id % SYS_TMM_MAX_MAC_NUM_PER_TXQM));
        }
    }
    else
    {
        factor = SYS_TMM_GET_MACID_PER_DP(port_attr->mac_id_aps) / SYS_TMM_MAX_MAC_NUM_PER_TXQM;
        fld_id = NetRxWrEnCtl_cfgWrEn0_f + step*factor;
        DRV_IOR_FIELD(lchip, NetRxWrEnCtl_t, fld_id, array32, &aps_en_ctl);
        /* protect path */
        if (rx_en)
        {
            CTC_BMP_SET(array32, (port_attr->mac_id_aps % SYS_TMM_MAX_MAC_NUM_PER_TXQM));
        }
        else
        {
            CTC_BMP_UNSET(array32, (port_attr->mac_id_aps % SYS_TMM_MAX_MAC_NUM_PER_TXQM));
        }
    }
    DRV_IOW_FIELD_NZ(lchip, NetRxWrEnCtl_t, fld_id, array32, &aps_en_ctl, dp_id, 0);
    cmd = DRV_IOW(NetRxWrEnCtl_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &aps_en_ctl);

    txqm_id = SYS_TMM_GET_TXQM_BY_MACID(mac_id);

     if (tx_en) /* mac tx enable */
    {
        /* #1, calc index */
        index = DRV_INS(txqm_id, 0);

        /* #2, read HW table: McMacMacTxCfg */
        tbl_id = McMacMacTxCfg_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mac_cfg));

        /* ##2.1. calc step */
        step = McMacMacTxCfg_cfgMcMacMacTx_1_cfgMcMacTxPktEn_f - McMacMacTxCfg_cfgMcMacMacTx_0_cfgMcMacTxPktEn_f;
        factor = SYS_TMM_GET_MACID_PER_TXQM(mac_id);/* 0..39 per txqm */

        /* ##2.2. modify field value */
        /* ###2.2.1. */
        fld_id = McMacMacTxCfg_cfgMcMacMacTx_0_cfgMcMacTxPktEn_f + step*factor;
        val32 = 1;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mac_cfg, txqm_id, 0);

        /* #3, write HW table: McMacMacTxCfg*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mac_cfg));
    }
    else
    {
        /* #1, calc index */
        index = DRV_INS(txqm_id, 0);

        /* #2, read HW table: McMacMacTxCfg */
        tbl_id = McMacMacTxCfg_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mac_cfg));

        /* ##2.1. calc step */
        step = McMacMacTxCfg_cfgMcMacMacTx_1_cfgMcMacTxPktEn_f - McMacMacTxCfg_cfgMcMacMacTx_0_cfgMcMacTxPktEn_f;
        factor = SYS_TMM_GET_MACID_PER_TXQM(mac_id);/* 0..39 per txqm */

        /* ##2.2. modify field value */
        /* ###2.2.1. */
        fld_id = McMacMacTxCfg_cfgMcMacMacTx_0_cfgMcMacTxPktEn_f + step*factor;
        val32 = 0;
        DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &mac_cfg, txqm_id, 0);

        /* #3, write HW table: McMacMacTxCfg*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mac_cfg));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_group_ohlock(uint8 lchip, sys_flexe_group_t *group_node, uint8 *p_ohlock)
{
    uint8 i                 = 0;
    uint8 inst_id           = 0;
    uint8 ohlock            = 1;
    uint8 val8              = 0;

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        inst_id = group_node->inst_list[i];
        CTC_ERROR_RETURN(_sys_tmm_flexe_get_inst_ohlock(lchip, group_node->flexe_shim_id, inst_id, &val8));
        if(!val8)
        {
            ohlock = 0;
            break;
        }
    }
    if (p_ohlock)
    {
        *p_ohlock = ohlock;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_group_ohmflock(uint8 lchip, sys_flexe_group_t *group_node, uint8 *p_ohmflock)
{
    uint8 i                 = 0;
    uint8 inst_id           = 0;
    uint8 ohmflock          = 1;
    uint8 val8              = 0;

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        inst_id = group_node->inst_list[i];
        CTC_ERROR_RETURN(_sys_tmm_flexe_get_inst_ohmflock(lchip, group_node->flexe_shim_id, inst_id, &val8));
        if(!val8)
        {
            ohmflock = 0;
            break;
        }
    }
    if (p_ohmflock)
    {
        *p_ohmflock = ohmflock;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_crcerr(uint8 lchip, uint8 flexe_shim_id, uint8 inst_id, uint32 *p_crc_cnt)
{
    uint32 tbl_id           = 0;
    uint32 fld_id           = 0;
    uint32 cmd              = 0;
    uint32 index            = 0;
    uint32 val32            = 0;
    uint32 step             = 0;
    uint32 factor           = 0;

    RxCrcErrCntInst0_m  cm;

    /* check crcErr count */
    index = DRV_INS(flexe_shim_id, 0);
    step = RxCrcErrCntInst1_t - RxCrcErrCntInst0_t;
    factor = inst_id; 
    tbl_id = RxCrcErrCntInst0_t + step*factor;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));
    fld_id = RxCrcErrCntInst0_val_f;
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &cm);

    if (p_crc_cnt)
    {
        *p_crc_cnt = val32;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_group_deskew(uint8 lchip, sys_flexe_group_t *group_node, uint8 *p_phy_skew)
{
    uint8 i                 = 0;
    uint8 inst_id           = 0;
    uint8 phy_skew          = 0;
    uint32 tbl_id           = 0;
    uint32 fld_id           = 0;
    uint32 cmd              = 0;
    uint32 index            = 0;
    uint32 val32            = 0;
    uint32 step             = 0;
    uint32 factor           = 0;

    RxLatchedIntInst0_m  cm;

    /* check each instance's deskewOverflow in the group */
    index = DRV_INS(group_node->flexe_shim_id, 0);
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        inst_id = group_node->inst_list[i];
        /* read ohlock in hard table */
        step = RxLatchedIntInst1_t - RxLatchedIntInst0_t;
        factor = inst_id; 
        tbl_id = RxLatchedIntInst0_t + step*factor;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));
        fld_id = RxLatchedIntInst0_deskewOverflow_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &cm);
        if(val32)
        {
            phy_skew = 1;
            break;
        }
    }

    if (p_phy_skew)
    {
        *p_phy_skew = phy_skew;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_inst_rpf(uint8 lchip, uint8 flexe_shim_id, uint8 asic_inst, uint8* p_rpf)
{
    uint32 index  = 0;
    uint32 cmd    = 0;
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 step   = 0;
    uint32 factor = 0;
    uint32 val32  = 0;
    uint8 rpf     = 0;
    RxLatchedIntInst0_m inst_sta_rx;

    /* #1, calc index */
    index = DRV_INS(flexe_shim_id, 0);

    /* #2, read HW table */
    step = RxLatchedIntInst1_t - RxLatchedIntInst0_t;
    factor = asic_inst;
    tbl_id = RxLatchedIntInst0_t + step*factor;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &inst_sta_rx);

    fld_id = RxLatchedIntInst0_RPF_f;
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &inst_sta_rx);
    rpf = (uint8)val32;

    if (p_rpf)
    {
        *p_rpf = rpf;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_inst_padlock(uint8 lchip, uint8 flexe_shim_id, uint8 asic_inst, uint8* p_padlock)
{
    uint32 index    = 0;
    uint32 cmd      = 0;
    uint32 tbl_id   = 0;
    uint32 fld_id   = 0;
    uint32 step     = 0;
    uint32 factor   = 0;
    uint32 val32    = 0;
    uint8 padlock   = 0;    
    RxLatchedIntInst0_m inst_sta_rx;

    /* #1, calc index */
    index = DRV_INS(flexe_shim_id, 0);

    /* #2, read HW table */
    step = RxLatchedIntInst1_t - RxLatchedIntInst0_t;
    factor = asic_inst;
    tbl_id = RxLatchedIntInst0_t + step*factor;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &inst_sta_rx);

    fld_id = RxLatchedIntInst0_padLock_f;
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &inst_sta_rx);
    padlock = (uint8)val32;

    if (p_padlock)
    {
        *p_padlock = padlock;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_mgr_intr_op_get(uint8 lchip, uint8 flexe_shim_id, uint8 inst_bmp, uint8 intr_type, uint8 op_type, uint8 *p_val)
{
    uint8  i = 0;
    uint8  j = 0;
    uint8  word_no = 0;
    uint8  bit = 0;
    uint8  offset = 0;
    uint32 cmd = 0;
    ds_t   ds;

    if (intr_type >= SYS_FLEXE_MGR_INTR_MAX_TYPE)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] FlexE mgr intr type %d out of range!\n", intr_type);
        return CTC_E_INVALID_PARAM;
    }

    if (INTR_INDEX_MASK_SET != op_type)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] FlexE mgr intr type get only support MASK!\n");
        return CTC_E_INVALID_PARAM;
    }

    *p_val = 0;
    cmd = DRV_IOR(FlexeMgrInterruptFunc_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, DRV_INS(flexe_shim_id, INTR_INDEX_MASK_SET), cmd, &ds);
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        if (0 == (inst_bmp & (1 << i)))
        {
            continue;
        }
        offset = i * SYS_FLEXE_MGR_INTR_NUM;
        for (j = 0; j < SYS_FLEXE_MGR_INTR_NUM; j++)
        {
            if (g_flexe_mgr_intr[offset+j].intr_type == intr_type)
            {
                word_no = g_flexe_mgr_intr[offset+j].word_no;
                bit     = g_flexe_mgr_intr[offset+j].bit;
                if (ds[word_no] & (0x1 << bit))
                {
                    *p_val = 1;
                    break;
                }
            }
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_is_recv_ca_and_cr_timeout(uint8 lchip, uint8 flexe_shim_id, uint8 inst_bmp, uint8 *is_recv_ca, uint8 *is_timeout)
{
    uint8  cs_id            = 0;
    uint8  txqm_id          = 0;
    uint8  base_serdes_id   = 0;
    uint8  inst_id          = 0;
    uint32 tbl_id           = 0;
    uint32 fld_id           = 0;
    uint32 cmd              = 0;
    uint32 index            = 0;
    uint32 val32            = 0;

    McHataReserved_m        cm;
    /* [0:7] is_timeout, bmp, per inst*/
    /* [16:23] is_recv_ca, bmp, per inst */ 

    /* 1, read HW table */
    SYS_FLEXE_SHIM_2_BASE_LOGIC_SERDES(flexe_shim_id, base_serdes_id);
    SYS_TMM_FLEXE_SERDES_2_CS(base_serdes_id, cs_id);
    SYS_TMM_FLEXE_CS_2_TXQM(cs_id, txqm_id);
    index = DRV_INS(txqm_id, 0);
    tbl_id = McHataReserved_t;
    fld_id = McHataReserved_mcataReserved_29_reserved_f;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &cm);

    /* 2, modified val*/
    for(inst_id = 0; inst_id < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); inst_id ++)
    {
        if (!CTC_IS_BIT_SET(inst_bmp, inst_id))
        {
            continue;
        }

        if(NULL != is_recv_ca)
        {
            if(TRUE == *is_recv_ca)
            {
                CTC_BIT_SET(val32, (16 + inst_id)); 
            }
            else
            {
                CTC_BIT_UNSET(val32, (16 + inst_id)); 
            }
        }

        if(NULL != is_timeout)
        {
            if(TRUE == *is_timeout)
            {
                CTC_BIT_SET(val32, inst_id); 
            }
            else
            {
                CTC_BIT_UNSET(val32, inst_id); 
            }
        }
    }

    /* 3, write HW table */
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &cm, txqm_id, 0);
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm)); 

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_is_recv_ca_and_cr_timeout(uint8 lchip, uint8 flexe_shim_id, uint8 inst_id, uint8 *is_recv_ca, uint8 *is_timeout)
{
    uint8  cs_id            = 0;
    uint8  txqm_id          = 0;
    uint8  base_serdes_id   = 0;
    uint32 cmd              = 0;
    uint32 index            = 0;
    uint32 val32            = 0;

    McHataReserved_m        cm;
    /* [0:7] is_timeout, bmp, per inst*/
    /* [16:23] is_recv_ca, bmp, per inst */ 

    /* 1, read HW table */
    SYS_FLEXE_SHIM_2_BASE_LOGIC_SERDES(flexe_shim_id, base_serdes_id);
    SYS_TMM_FLEXE_SERDES_2_CS(base_serdes_id, cs_id);
    SYS_TMM_FLEXE_CS_2_TXQM(cs_id, txqm_id);
    index = DRV_INS(txqm_id, 0);
    cmd = DRV_IOR(McHataReserved_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));
    DRV_IOR_FIELD(lchip, McHataReserved_t, McHataReserved_mcataReserved_29_reserved_f, &val32, &cm);

    /* 2.1 get is_recv_ca*/
    if(NULL != is_recv_ca)
    {
        *is_recv_ca = CTC_IS_BIT_SET(val32, (16 + inst_id));
    }

    /* 2.2 get is_timeout*/
    if(NULL != is_timeout)
    {
        *is_timeout = CTC_IS_BIT_SET(val32, inst_id);
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_cfgrxoh_sync(uint8 lchip, sys_flexe_group_t* group_node, uint32 enable)
{
    uint8 i = 0;
    uint8 speed_mode = 0;
    uint8 asic_inst = 0;
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;
    uint8 flexe_shim_id = 0;

    FlexeMgrOhCfg_m  cm;

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);

    flexe_shim_id = group_node->flexe_shim_id;
    tbl_id = FlexeMgrOhCfg_t;
    index = DRV_INS(flexe_shim_id, 0);

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));
    fld_id = FlexeMgrOhCfg_cfgRxOhSyncEn_f;
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &cm);

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        asic_inst = group_node->inst_list[i];
        if((speed_mode == CTC_PORT_SPEED_50G) || ((speed_mode != CTC_PORT_SPEED_50G) && (0 == asic_inst%2)))
        {
            if(enable)
            {
                val32 |= (1 << asic_inst);
            }
            else
            {
                val32 &= ~(1 << asic_inst);
            }
        }
    }
    DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &cm, flexe_shim_id, 0);

    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_cfgrxoh_sync(uint8 lchip, sys_flexe_group_t* group_node, uint32* p_enable)
{
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 val32  = 0;

    FlexeMgrOhCfg_m  cm;

    /* #1, calc index */
    index = DRV_INS(group_node->flexe_shim_id, 0);

    /* #2, read HW table */
    tbl_id = FlexeMgrOhCfg_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm));

    fld_id = FlexeMgrOhCfg_cfgRxOhSyncEn_f;
    DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32, &cm);

    /* #3, get value of group first instance */
    if (p_enable)
    {
        *p_enable = (val32 >> group_node->inst_list[0]) & 1;
    }

    return CTC_E_NONE;
}

#define ____FLEXE_INIT_DS____
/*
 * Init Data structure
 *  - Reset data to
 *   1) IDLE state
 *   2) Illegal value
 *  - called when create/add and destroy/remove
 */
 STATIC int32
_sys_tmm_flexe_init_group_sch_ds(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 k = 0;
    sys_flexe_group_dir_t *p_group_dir = NULL;

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); i++)
    {
        p_group_dir->cc[i].cycle_value = SYS_FLEXE_UNUSED_FLAG_U8;
        p_group_dir->cc[i].shim_chid   = 0;
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); j++)
        {
            p_group_dir->cc[i].inst[j].slot_cnt      = 0;
            p_group_dir->cc[i].inst[j].cc_subcalmask = 0x0;
            for (k = 0; k < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); k++)
            {
                p_group_dir->cc[i].inst[j].slot_list[k] = SYS_FLEXE_UNUSED_FLAG_U8;
            }
        }
    }
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); j++)
        {
            p_group_dir->ic[i][j].shim_chid     = 0;
            p_group_dir->ic[i][j].ic_subcalmask = 0;
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_init_group_phy_ds(uint8 lchip, sys_flexe_group_t *group_node, uint8 is_unbind)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 k = 0;

    for (i = 0; i < group_node->phy_cnt; i++)
    {
        group_node->phy_list[i].phy_number          = 0;
        group_node->phy_list[i].logical_serdes_base = SYS_FLEXE_UNUSED_FLAG_U8;
        group_node->phy_list[i].inst_base           = SYS_FLEXE_UNUSED_FLAG_U8;
        group_node->phy_list[i].pcs_mode            = CTC_CHIP_MAX_SERDES_MODE;
        group_node->phy_list[i].fec_type            = CTC_PORT_FEC_TYPE_MAX;
        group_node->phy_list[i].crc_cnt             = 0;
        group_node->phy_list[i].event_bmp           = 0;
        CTC_BIT_SET(group_node->phy_list[i].event_bmp, CTC_FLEXE_EVENT_LOF);
        CTC_BIT_SET(group_node->phy_list[i].event_bmp, CTC_FLEXE_EVENT_LOMF);
        CTC_BIT_SET(group_node->phy_list[i].event_bmp, CTC_FLEXE_EVENT_RPF);
        CTC_BIT_SET(group_node->phy_list[i].event_bmp, CTC_FLEXE_EVENT_LPF);
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_OH_PHY_INST_CNT); j++)
        {
            group_node->phy_list[i].remote_state[j].inst_offset     = 0;
            group_node->phy_list[i].remote_state[j].event_bmp       = 0;
            group_node->phy_list[i].remote_state[j].group_num       = 0;
            group_node->phy_list[i].remote_state[j].instance_num    = 0;
            for (k = 0; k < SYS_FLEXE_OH_FRAME_NUM; k++)
            {
                group_node->phy_list[i].remote_state[j].flexe_map[k] = 0;
            }
            for (k = 0; k < SYS_FLEXE_OH_MAX_SLOT_PER_INST; k++)
            {
                group_node->phy_list[i].remote_state[j].client_map[k] = 0;
                group_node->phy_list[i].remote_state[j].client_map_b[k] = 0;
            }
        }
    }

    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        group_node->inst_list[i]  = SYS_FLEXE_UNUSED_FLAG_U8;
    }

    /* tx */
    group_node->tx.active     = SYS_FLEXE_ACTIVE_A;
    group_node->tx.crac_state = SYS_FLEXE_GROUP_TX_IDLE;
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            group_node->tx.dir_inst[i].slot_cfg_shim_chid[j] = 0;
            group_node->tx.dir_inst[i].switch_shim_chid_a[j] = 0;
            group_node->tx.dir_inst[i].switch_shim_chid_b[j] = 0;
        }
        group_node->tx.dir_inst[i].flush_bmp          = 0x0;
        group_node->tx.dir_inst[i].cr_flip            = SYS_FLEXE_OH_FLIP_MAX;  /* TX cr/ca/c flip is useless */
        group_node->tx.dir_inst[i].ca_flip            = SYS_FLEXE_OH_FLIP_MAX;
        group_node->tx.dir_inst[i].c_flip             = SYS_FLEXE_OH_FLIP_MAX;
    }
    _sys_tmm_flexe_init_group_sch_ds(lchip, group_node, SYS_FLEXE_DIR_TX);

    /* rx */
    group_node->rx.active     = SYS_FLEXE_ACTIVE_A;
    group_node->rx.crac_state = SYS_FLEXE_GROUP_RX_IDLE;
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            group_node->rx.dir_inst[i].slot_cfg_shim_chid[j] = 0;
            group_node->rx.dir_inst[i].switch_shim_chid_a[j] = 0;
            group_node->rx.dir_inst[i].switch_shim_chid_b[j] = 0;
        }
        group_node->rx.dir_inst[i].flush_bmp          = 0x0;
        group_node->rx.dir_inst[i].cr_flip            = SYS_FLEXE_OH_FLIP_NONE;
        group_node->rx.dir_inst[i].ca_flip            = SYS_FLEXE_OH_FLIP_NONE;
        group_node->rx.dir_inst[i].c_flip             = SYS_FLEXE_OH_FLIP_NONE;
    }
    _sys_tmm_flexe_init_group_sch_ds(lchip, group_node, SYS_FLEXE_DIR_RX);

    if (is_unbind)
    {
        group_node->flexe_shim_id               = SYS_FLEXE_UNSUPP;
        group_node->inst_cnt                    = 0;
        group_node->phy_cnt                     = 0;
        group_node->event_bmp                   = 0;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_init_group_ds(uint8 lchip, sys_flexe_group_t *group_node)
{
    group_node->group_number                = 0;
    group_node->switch_mode                 = SYS_FLEXE_SWITCH_MODE_MAX;
    group_node->rx_cfg_mode                 = SYS_FLEXE_RX_F0LLOW_REMOTE;
    group_node->flexe_shim_id               = SYS_FLEXE_UNSUPP;
    group_node->inst_cnt                    = 0;
    group_node->phy_cnt                     = 0;
    group_node->event_bmp                   = 0;
    group_node->cr_timer                    = 0;
    group_node->pad_en                      = 1;

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_init_client_ds(uint8 lchip, sys_flexe_client_t *client_node)
{
    client_node->client_id       = SYS_FLEXE_UNUSED_FLAG_U32;
    client_node->client_number   = 0;
    client_node->group_id        = SYS_FLEXE_UNUSED_FLAG_U32;

    client_node->flexe_shim_id   = SYS_FLEXE_UNSUPP;
    client_node->shim_chid       = 0;
    client_node->tx_xc_chid      = SYS_FLEXE_UNUSED_FLAG_U8;
    client_node->rx_xc_chid      = SYS_FLEXE_UNUSED_FLAG_U8;

    client_node->cross_client_id = SYS_FLEXE_UNUSED_FLAG_U32;
    client_node->gport           = SYS_FLEXE_UNUSED_FLAG_U32;

    client_node->mac_id          = SYS_FLEXE_UNUSED_FLAG_U16;
    client_node->chan_id         = SYS_FLEXE_UNUSED_FLAG_U8;
    client_node->cross_enable    = 0;
    client_node->aps_role        = 0;
    client_node->bind_oam        = 0;
    client_node->flow_type       = SYS_FLEXE_FLOW_MAX;

    client_node->tx.op           = SYS_FLEXE_CLIENT_MAX;
    client_node->tx.read_ptr     = 0;
    client_node->rx.op           = SYS_FLEXE_CLIENT_MAX;
    client_node->rx.read_ptr     = 0;

    return CTC_E_NONE;
}

#define ____FLEXE_PARAM_CHECK____

STATIC int32
_sys_tmm_flexe_check_group_client_number_same(uint8 lchip, uint32 client_number, uint32 group_id)
{
    uint8 client_num_same = FALSE;
    sys_flexe_client_t* tmp_client_node = NULL;
    ctc_slistnode_t* node = NULL;

    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
    {
        tmp_client_node = _ctc_container_of(node, sys_flexe_client_t, head);
        if (tmp_client_node)
        {
            if ((0 != client_number)  /* 0 is default/illegal value */
                && (client_number == tmp_client_node->client_number)
                && (group_id == tmp_client_node->group_id)
                && (SYS_FLEXE_UNUSED_FLAG_U32 != tmp_client_node->client_id))
            {
                client_num_same = TRUE;
                break;
            }
        }
    }

    if (client_num_same)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client_number %d is used by other client in group %d!\n", \
            client_number, group_id);
        return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_slot_phy_different(uint8 lchip, ctc_flexe_client_slot_t* p_slot, uint8 *p_slot_phy_diff)
{
    uint8 i = 0, j = 0;
    uint8 arr[TMM_GROUP_MAX_PHY_CNT];
    uint8 slot_serdes_diff = 1;
    uint8 logical_serdes_id = 0;
    uint8 flag = 0;
    sys_flexe_phy_t* phy_node = NULL;

    for (i = 0; i < p_slot->phy_cnt; i++)
    {
        _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)p_slot->slot[i].serdes_id, &logical_serdes_id);
        SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
        phy_node = _sys_tmm_flexe_get_phy_node(lchip, logical_serdes_id);
        if (!phy_node)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] phy %d has not added to any FlexE group!\n", p_slot->slot[i].serdes_id);
            return CTC_E_NOT_EXIST;
        }
        arr[i] = phy_node->logical_serdes_base;
    }

    for (i = 0; i < p_slot->phy_cnt; i++)
    {
        for (j = i+1;j < p_slot->phy_cnt ; j++)
        {
            if(arr[i] == arr[j])
            {
                flag = 1;
                slot_serdes_diff = 0;
                break;
            }
        }
        if (flag == 1)
        {
            break;
        }
    }

    if (p_slot_phy_diff)
    {
        *p_slot_phy_diff = slot_serdes_diff;
    }

    return CTC_E_NONE;
}

/*
 * Two called scenario:
 *  1) client resize slot(without switch) after bind port
 *  2) bind port after client (add/resize) slot then switch
 */
STATIC int32
_sys_tmm_flexe_check_nettx_credit(uint8 lchip, sys_flexe_client_t *client_node, uint8 user_slot_cnt)
{
    uint8   i = 0;
    uint8   txqm_id = 0;
    uint16  tmp_mac = 0;
    uint32  sum_nettx = 0;
    uint32  tmp_nettx = 0;
    uint32  tx_cfg_speed = 0;
    uint32  rx_cfg_speed = 0;
    uint32  cfg_speed = 0;
    sys_flexe_client_t *tmp_client_node = NULL;
    sys_flexe_group_t  *tmp_group_node = NULL;

    /*check whether resize slot MAY cause datapath nettx resource exhaused */
    txqm_id = client_node->mac_id / SYS_TMM_MAX_MAC_NUM_PER_TXQM;
    sum_nettx = _sys_tmm_nettx_speed_to_credit(SYS_FLEXE_SLOT_SPEED*user_slot_cnt);
    FLEXE_DBG_PRINTF("client %d new-config slot cnt %d(NetTx based speed is %d) sum_nettx = %d\n", client_node->client_id, \
        user_slot_cnt, SYS_FLEXE_SLOT_SPEED*user_slot_cnt, sum_nettx);

    /* check nettx checksum */
    for (i = 0; i < SYS_TMM_MAX_MAC_NUM_PER_TXQM; i++)
    {
        tmp_client_node = NULL;
        tmp_mac = txqm_id * SYS_TMM_MAX_MAC_NUM_PER_TXQM + i;
        _sys_tmm_flexe_client_lookup_by_mac(lchip, tmp_mac, &tmp_client_node);
        SYS_CONDITION_CONTINUE(!tmp_client_node);
        SYS_CONDITION_CONTINUE(SYS_FLEXE_UNUSED_FLAG_U32 == tmp_client_node->gport);
        SYS_CONDITION_CONTINUE(client_node->mac_id == tmp_mac);

        _sys_tmm_flexe_group_lookup(lchip, tmp_client_node->group_id, &tmp_group_node);
        SYS_CONDITION_CONTINUE(!tmp_group_node);
        _sys_tmm_flexe_get_client_speed_val(lchip, tmp_client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_CFG_FLAG, &tx_cfg_speed);
        _sys_tmm_flexe_get_client_speed_val(lchip, tmp_client_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_CFG_FLAG, &rx_cfg_speed);
        cfg_speed = (tx_cfg_speed > rx_cfg_speed) ? tx_cfg_speed : rx_cfg_speed;
        tmp_nettx = _sys_tmm_nettx_speed_to_credit(cfg_speed);
        sum_nettx += tmp_nettx;
        FLEXE_DBG_PRINTF("%d. client %d speed %d sum_nettx = %d\n", i, \
            tmp_client_node->client_id, cfg_speed, sum_nettx);
        if (sum_nettx > 200)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Client %d new speed is %dG, will result in TXQM %d NetTx credit resource exhausted, resize fail, please remove this client and add new one! \n", \
                client_node->client_id, cfg_speed, txqm_id);
            return CTC_E_NO_RESOURCE;
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_idle_macid(uint8 lchip, uint8 txqm_id, uint32 calc_speed, sys_flexe_dir_t dir, uint16* p_mac_id, uint8 *p_ret)
{
    uint8   i = 0;
    uint16  mac_id = 0;
    uint32  cfg_speed = 0;
    uint32  sum_nettx = 0;
    uint32  tmp_nettx = 0;
    int32   ret = CTC_E_NONE;
    sys_flexe_client_t *client_node = NULL;

    *p_ret = SYS_FLEXE_ALLOC_SUCCESS;

    ret = sys_tmm_datapath_get_idle_macid(lchip, SYS_ARRANGE_FLEXE_PORT_BMP, txqm_id, p_mac_id);
    if (ret)
    {
        *p_ret = SYS_FLEXE_ALLOC_RET_NO_MAC;
        return ret;
    }

    sum_nettx = _sys_tmm_nettx_speed_to_credit(calc_speed);

    /* check nettx checksum */
    for (i = 0; i < SYS_TMM_MAX_MAC_NUM_PER_TXQM; i++)
    {
        client_node = NULL;
        mac_id = txqm_id * SYS_TMM_MAX_MAC_NUM_PER_TXQM + i;
        _sys_tmm_flexe_client_lookup_by_mac(lchip, mac_id, &client_node);
        SYS_CONDITION_CONTINUE(!client_node);
        _sys_tmm_flexe_get_client_speed_val(lchip, client_node, dir, SYS_FLEXE_CFG_FLAG, &cfg_speed);
        tmp_nettx = _sys_tmm_nettx_speed_to_credit(cfg_speed);
        sum_nettx += tmp_nettx;
        if (sum_nettx > 200)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] TXQM %d NetTx credit resource exhausted, now try to find another FlexE-enabled TXQM...\n", txqm_id);
            FLEXE_DUMP("[FlexE] TXQM %d NetTx credit resource exhausted, now try to find another FlexE-enabled TXQM...\n", txqm_id);
            ret = CTC_E_INVALID_CONFIG;
            *p_ret = SYS_FLEXE_ALLOC_RET_NO_CREDIT;
            break;
        }
    }

    return ret;
}

STATIC int32
_sys_tmm_flexe_client_alloc_mac_check(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_client_t* client_node, uint8 user_slot_cnt, sys_flexe_dir_t dir, uint16* p_mac_id)
{
    uint8 i = 0;
    uint8 cs_id = 0;
    uint8 txqm_res[2] = {0};
    uint8 flexe_en = 0;
    uint8 cs_flexe_en[2] = {0};
    uint16 mac_id = 0;
    int32 ret = 0;
    uint8 txqm_id = 0;
    uint8 alloc_ret = 0;

    for (i = 0; i < group_node->phy_cnt; i++)
    {
        SYS_CONDITION_CONTINUE(SYS_FLEXE_UNUSED_FLAG_U8 == group_node->phy_list[i].logical_serdes_base);

        SYS_TMM_GET_TXQM_BY_SERDES(group_node->phy_list[i].logical_serdes_base, txqm_id);
        if (0 == (txqm_id % 2))
        {
            txqm_res[0] = txqm_id;
        }
        if (1 == (txqm_id % 2))
        {
            txqm_res[1] = txqm_id;
        }
    }

    for (i = 0; i < TMM_MAX_CS_NUM_PER_SHIM; i++)
    {
        cs_id = i + group_node->flexe_shim_id * 2;
        CTC_ERROR_RETURN(_sys_tmm_flexe_get_enable(lchip, cs_id, &flexe_en));
        cs_flexe_en[i] = flexe_en;
    }

    /* alloc free mac id */
    if (txqm_res[0] && txqm_res[1]) /* CS 0/1 PHY involved in the group */
    {
        txqm_id = txqm_res[0]; /* use CS 0 first */
        FLEXE_DUMP("-- client %d alloc txqm %d mac, speed is %d\n", client_node->client_id, txqm_id, SYS_FLEXE_SLOT_SPEED*user_slot_cnt);
        ret = _sys_tmm_flexe_get_idle_macid(lchip, txqm_id, SYS_FLEXE_SLOT_SPEED*user_slot_cnt, dir, &mac_id, &alloc_ret);
        if (ret)  /* CS 0 MAC/credit exhaused */
        {
            txqm_id = txqm_res[1];  /* then use CS 1, now client use CS 0 MAC and CS 1 PHY */
            FLEXE_DUMP("-- client %d alloc txqm %d mac, speed is %d\n", client_node->client_id, txqm_id, SYS_FLEXE_SLOT_SPEED*user_slot_cnt);
            ret = _sys_tmm_flexe_get_idle_macid(lchip, txqm_id, SYS_FLEXE_SLOT_SPEED*user_slot_cnt, dir, &mac_id, &alloc_ret);
            if (ret)  /* CS 1 MAC/credit exhaused */
            {
                if (SYS_FLEXE_ALLOC_RET_NO_MAC == alloc_ret)
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "[FlexE] { %s @ %d } TXQM %d MAC alloc fail, no resource\n", __FUNCTION__, __LINE__, txqm_id);
                    return CTC_E_NO_RESOURCE;
                }
                else if (SYS_FLEXE_ALLOC_RET_NO_CREDIT == alloc_ret)
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "[FlexE] { %s @ %d } TXQM %d NetTx Credit exhaust, no resource\n", __FUNCTION__, __LINE__, txqm_id);
                    return CTC_E_NO_RESOURCE;
                }
            }
        }
    }
    else if (txqm_res[0] && !txqm_res[1])  /* only CS 0 PHY involved in the group */
    {
        txqm_id = txqm_res[0];
        FLEXE_DUMP("-- client %d alloc txqm %d mac, speed is %d\n", client_node->client_id, txqm_id, SYS_FLEXE_SLOT_SPEED*user_slot_cnt);
        ret = _sys_tmm_flexe_get_idle_macid(lchip, txqm_id, SYS_FLEXE_SLOT_SPEED*user_slot_cnt, dir, &mac_id, &alloc_ret);
        if (ret)  /* CS 0 MAC/credit exhaused */
        {
            if (cs_flexe_en[1])  /* CS 1 PHY enabled FlexE */
            {
                txqm_id = 3 + 4*client_node->flexe_shim_id; /* client use CS 1 MAC and CS 0 PHY */
                FLEXE_DUMP("-- client %d alloc txqm %d mac, speed is %d\n", client_node->client_id, txqm_id, SYS_FLEXE_SLOT_SPEED*user_slot_cnt);
                ret = _sys_tmm_flexe_get_idle_macid(lchip, txqm_id, SYS_FLEXE_SLOT_SPEED*user_slot_cnt, dir, &mac_id, &alloc_ret);
                if (ret)  /* CS 1 MAC/credit exhaused */
                {
                    if (SYS_FLEXE_ALLOC_RET_NO_MAC == alloc_ret)
                    {
                        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "[FlexE] { %s @ %d } TXQM %d MAC alloc fail, no resource\n", __FUNCTION__, __LINE__, txqm_id);
                        return CTC_E_NO_RESOURCE;
                    }
                    else if (SYS_FLEXE_ALLOC_RET_NO_CREDIT == alloc_ret)
                    {
                        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "[FlexE] { %s @ %d } TXQM %d NetTx Credit exhaust, no resource\n", __FUNCTION__, __LINE__, txqm_id);
                        return CTC_E_NO_RESOURCE;
                    }
                }
            }
            else /* CS 1 PHY not enabled FlexE */
            {
                if (SYS_FLEXE_ALLOC_RET_NO_MAC == alloc_ret)
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "[FlexE] { %s @ %d } TXQM %d MAC alloc fail, no resource\n", __FUNCTION__, __LINE__, txqm_res[0]);
                    return CTC_E_NO_RESOURCE;
                }
                else if (SYS_FLEXE_ALLOC_RET_NO_CREDIT == alloc_ret)
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "[FlexE] { %s @ %d } TXQM %d NetTx Credit exhaust, no resource\n", __FUNCTION__, __LINE__, txqm_res[0]);
                    return CTC_E_NO_RESOURCE;
                }
            }
        }
    }
    else if (!txqm_res[0] && txqm_res[1])  /* only CS 1 PHY involved in the group */
    {
        txqm_id = txqm_res[1];
        FLEXE_DUMP("-- client %d alloc txqm %d mac, speed is %d\n", client_node->client_id, txqm_id, SYS_FLEXE_SLOT_SPEED*user_slot_cnt);
        ret = _sys_tmm_flexe_get_idle_macid(lchip, txqm_id, SYS_FLEXE_SLOT_SPEED*user_slot_cnt, dir, &mac_id, &alloc_ret);
        if (ret)  /* CS 1 MAC/credit exhaused */
        {
            if (cs_flexe_en[0])  /* CS 0 PHY enabled FlexE */
            {
                txqm_id = 2 + 4*client_node->flexe_shim_id; /* client use CS 0 MAC and CS 1 PHY */
                FLEXE_DUMP("-- client %d alloc txqm %d mac, speed is %d\n", client_node->client_id, txqm_id, SYS_FLEXE_SLOT_SPEED*user_slot_cnt);
                ret = _sys_tmm_flexe_get_idle_macid(lchip, txqm_id, SYS_FLEXE_SLOT_SPEED*user_slot_cnt, dir, &mac_id, &alloc_ret);
                if (ret)  /* CS 0 MAC/credit exhaused */
                {
                    if (SYS_FLEXE_ALLOC_RET_NO_MAC == alloc_ret)
                    {
                        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "[FlexE] { %s @ %d } TXQM %d MAC alloc fail, no resource\n", __FUNCTION__, __LINE__, txqm_id);
                        return CTC_E_NO_RESOURCE;
                    }
                    else if (SYS_FLEXE_ALLOC_RET_NO_CREDIT == alloc_ret)
                    {
                        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "[FlexE] { %s @ %d } TXQM %d NetTx Credit exhaust, no resource\n", __FUNCTION__, __LINE__, txqm_id);
                        return CTC_E_NO_RESOURCE;
                    }
                }
            }
            else /* CS 0 PHY not enabled FlexE */
            {
                if (SYS_FLEXE_ALLOC_RET_NO_MAC == alloc_ret)
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "[FlexE] { %s @ %d } TXQM %d MAC alloc fail, no resource\n", __FUNCTION__, __LINE__, txqm_res[1]);
                    return CTC_E_NO_RESOURCE;
                }
                else if (SYS_FLEXE_ALLOC_RET_NO_CREDIT == alloc_ret)
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "[FlexE] { %s @ %d } TXQM %d NetTx Credit exhaust, no resource\n", __FUNCTION__, __LINE__, txqm_res[1]);
                    return CTC_E_NO_RESOURCE;
                }
            }
        }
    }

    if (p_mac_id)
    {
        *p_mac_id = mac_id;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_phy_used(uint8 lchip, ctc_flexe_phy_t *phylist)
{
    uint8  i = 0;
    uint8  logical_serdes_id = 0;
    sys_flexe_group_t* tmp_group_node = NULL;
    int32  ret = 0;

    for (i = 0; i < phylist->serdes_cnt; i++)
    {
        _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)phylist->serdes_id[i], &logical_serdes_id);
        SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
        tmp_group_node = _sys_tmm_flexe_group_lookup_by_serdes(lchip, logical_serdes_id);
        if (tmp_group_node)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] SerDes ID %d is used by other group\n", phylist->serdes_id[i]);
            ret = CTC_E_EXIST;
        }
    }

    return ret;
}

STATIC int32
_sys_tmm_flexe_check_phy_flexe_en(uint8 lchip, ctc_flexe_phy_t *phylist)
{
    uint8 i = 0;
    uint8 flexe_en = 0;
    uint8 cs_id = 0;

    for (i = 0; i < phylist->serdes_cnt; i++)
    {
        SYS_TMM_FLEXE_SERDES_2_CS(phylist->serdes_id[i], cs_id);
        CTC_ERROR_RETURN(_sys_tmm_flexe_get_enable(lchip, cs_id, &flexe_en));
        if (!flexe_en)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] SerDes ID %d not enable FlexE \n", phylist->serdes_id[i]);
            return CTC_E_NOT_READY;
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_fec(uint8 lchip, ctc_flexe_phy_t *phylist, uint8 *p_fec_same)
{
    uint8 i = 0;
    uint8 logical_serdes_id = 0;
    uint32 fec_list[TMM_GROUP_MAX_PHY_CNT] = {0};
    uint8 fec_same = TRUE;
    sys_datapath_serdes_info_t* p_serdes  = NULL;

    for (i = 0 ;i < phylist->serdes_cnt; i++)
    {
        _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)phylist->serdes_id[i], &logical_serdes_id);
        SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
        CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, logical_serdes_id, &p_serdes));
        fec_list[i] = p_serdes->fec_type;
    }

    for (i = 0 ;i < phylist->serdes_cnt; i++)
    {
        if (fec_list[i] != fec_list[0])
        {
            fec_same = FALSE;
        }
    }

    if (p_fec_same)
    {
        *p_fec_same = fec_same;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_dp_fec(uint8 lchip, uint8 flexe_shim_id, ctc_flexe_phy_t *phylist)
{
    uint8 lg_nonefec = 0;
    uint8 lg_nonefec2 = 0;
    uint8 logical_serdes_id = 0;
    sys_flexe_group_t* tmp_group_node = NULL;
    ctc_slistnode_t* node = NULL;
    sys_datapath_serdes_info_t* p_serdes  = NULL;

    /* get new commer phy fec */
    _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)phylist->serdes_id[0], &logical_serdes_id);
    SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
    CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, logical_serdes_id, &p_serdes));
    if (((CTC_CHIP_SERDES_LG_R1_MODE == p_serdes->mode) || (CTC_CHIP_SERDES_LG_MODE == p_serdes->mode)) && \
        (CTC_PORT_FEC_TYPE_NONE == p_serdes->fec_type))
    {
        lg_nonefec = 1;
    }

    /* compare with old phy */
    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->group_list, node)
    {
        tmp_group_node = _ctc_container_of(node, sys_flexe_group_t, head);
        SYS_CONDITION_CONTINUE(NULL == tmp_group_node);
        SYS_CONDITION_CONTINUE(tmp_group_node->flexe_shim_id != flexe_shim_id);
        SYS_CONDITION_CONTINUE(!tmp_group_node->phy_cnt);
        if (((CTC_CHIP_SERDES_LG_R1_MODE == tmp_group_node->phy_list[0].pcs_mode) || (CTC_CHIP_SERDES_LG_MODE == tmp_group_node->phy_list[0].pcs_mode)) && \
            (CTC_PORT_FEC_TYPE_NONE == tmp_group_node->phy_list[0].fec_type))
        {
            lg_nonefec2 = 1;
        }
        else
        {
            lg_nonefec2 = 0;
        }
        if (lg_nonefec != lg_nonefec2)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] not support LG NoneFec PHY combine with other PHY in a shim!\n");
            return CTC_E_INVALID_PARAM;
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_phy_speed(uint8 lchip, ctc_flexe_phy_t *phylist, uint32 *p_same)
{
    uint8 i = 0;
    uint8 logical_serdes_id = 0;
    uint32 same = 1;
    uint32 speed_list[TMM_GROUP_MAX_PHY_CNT] = {0};
    uint32 iftype_list[TMM_GROUP_MAX_PHY_CNT] = {0};
    sys_datapath_serdes_info_t* p_serdes  = NULL;

    for (i = 0; i < phylist->serdes_cnt; i++)
    {
        _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)phylist->serdes_id[i], &logical_serdes_id);
        SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
        CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, logical_serdes_id, &p_serdes));
        _sys_tmm_flexe_get_phy_ifmode(lchip, p_serdes, &speed_list[i], &iftype_list[i]);
        if (speed_list[i] == CTC_PORT_SPEED_MAX)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] SerDes mode is not supported \n");
            return CTC_E_NOT_READY;
        }
    }
    for (i = 0; i < phylist->serdes_cnt - 1; i++)
    {
        if ((speed_list[i] != speed_list[i+1]) || (iftype_list[i] != iftype_list[i+1]))
        {
            same = 0;
        }
    }

    if (p_same)
    {
        *p_same = same;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_phy_shim_id_same(ctc_flexe_phy_t *phylist, uint32 *p_shim_same)
{
    uint8 i = 0;
    uint8 arr[TMM_GROUP_MAX_PHY_CNT] = {0};
    uint32 shim_same = 1;
    for (i = 0; i < phylist->serdes_cnt; i++)
    {
        arr[i] = SYS_TMM_FLEXE_GET_FLEXE_SHIM(phylist->serdes_id[i]);
    }

    for (i = 0 ;i < phylist->serdes_cnt ; i++)
    {
        if (arr[i]!=arr[0])
        {
            shim_same=0;
        }
    }

    if (p_shim_same)
    {
        *p_shim_same = shim_same;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_serdes_phy_same(uint8 lchip, ctc_flexe_phy_t *phylist, uint8 *p_serdes_phy_diff)
{
    uint8 i = 0, j = 0;
    uint8 serdes_phy_diff = TRUE;
    uint8 serdes_base[TMM_GROUP_MAX_PHY_CNT] = {0};
    uint32 phy_speed = 0;
    uint32 phy_iftype = 0;
    uint8 logical_serdes_id = 0;
    uint32 phy_lane_num = 0;
    sys_datapath_serdes_info_t* p_serdes  = NULL;

    for (i = 0; i < phylist->serdes_cnt; i++)
    {
        _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)phylist->serdes_id[i], &logical_serdes_id);
        SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
        CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, logical_serdes_id, &p_serdes));
        _sys_tmm_flexe_get_phy_ifmode(lchip, p_serdes, &phy_speed, &phy_iftype);
        switch (phy_iftype)
        {
        case CTC_PORT_IF_CR2:
            phy_lane_num = 2;
            break;
        case CTC_PORT_IF_CR4:
            phy_lane_num = 4;
            break;
        case CTC_PORT_IF_CR8:
            phy_lane_num = 8;
            break;
        case CTC_PORT_IF_CR:
        default:
            phy_lane_num = 1;
            break;
        }
        serdes_base[i] = logical_serdes_id - logical_serdes_id%phy_lane_num;
    }

    for (i = 0; i < phylist->serdes_cnt; i++)
    {
        for (j = i+1; j <phylist->serdes_cnt ; j++)
        {
            if(serdes_base[i] == serdes_base[j])
            {
                serdes_phy_diff = FALSE;
                break;
            }
        }
    }

    if (p_serdes_phy_diff)
    {
        *p_serdes_phy_diff = serdes_phy_diff;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_total_inst_cnt(uint8 lchip, ctc_flexe_phy_t *phylist, uint32 phy_inst_cnt, uint32 *p_inst_num_total)
{
    uint8 i = 0;
    uint8 used = 0;
    uint8 flexe_shim_id = 0;
    uint32 inst_num_total = 0;
    uint8 logical_serdes_id = 0;

    _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)phylist->serdes_id[0], &logical_serdes_id);
    SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
    flexe_shim_id = SYS_TMM_FLEXE_GET_FLEXE_SHIM(logical_serdes_id);

    /* Calculate the initial state of inst_num_total */
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        _sys_tmm_flexe_check_inst_used(lchip, flexe_shim_id, i, &used);
        if (used)
        {
            inst_num_total++;
        }
    }
    for (i = 0; i < phylist->serdes_cnt; i++)
    {
        inst_num_total += phy_inst_cnt;
    }
    if (p_inst_num_total)
    {
        *p_inst_num_total = inst_num_total;    /* calculate instance num include newcoming */
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_shim_pad_same(uint8 lchip, uint8 flexe_shim_id, uint8 pad)
{
    sys_flexe_group_t* tmp_group_node = NULL;
    ctc_slistnode_t* node = NULL;

    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->group_list, node)
    {
        tmp_group_node = _ctc_container_of(node, sys_flexe_group_t, head);
        SYS_CONDITION_CONTINUE(tmp_group_node->flexe_shim_id != flexe_shim_id);
        if (tmp_group_node->pad_en != pad)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] not support pad_disable LG PHY combine with other PHY in a shim!\n");
            return CTC_E_INVALID_PARAM;
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_bind_phylist_pc(uint8 lchip, sys_flexe_group_t* group_node, ctc_flexe_phy_t *phylist)
{
    uint8  flexe_shim_id      = 0;
    uint32 inst_num_total     = 0;
    uint32 phy_inst_cnt       = 0;
    uint32 same               = 0;
    uint32 shim_same          = 0;
    uint8  serdes_phy_diff    = TRUE;
    uint8  fec_same           = TRUE;
    uint8  logical_serdes_id  = 0;
    sys_datapath_serdes_info_t* p_serdes  = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /* check whether group phy list empty or not */
    if (group_node->phy_cnt)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] FlexE group ID %d is not empty!\n", group_node->group_id);
        return CTC_E_EXIST;
    }

    flexe_shim_id = SYS_TMM_FLEXE_GET_FLEXE_SHIM(phylist->serdes_id[0]);
    if (SYS_FLEXE_UNSUPP == flexe_shim_id)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] SerDes ID %d not support FlexE \n", phylist->serdes_id[0]);
        return CTC_E_INVALID_PARAM;
    }

    /* check whether phy list are conflict with other group */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_phy_used(lchip, phylist));

    /* check whether phy(serdes) have enable FlexE */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_phy_flexe_en(lchip, phylist));

    /* check whether phy fec mode are all the same */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_fec(lchip, phylist, &fec_same));
    if (fec_same == FALSE)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] PHY list fec mode not all the same!\n");
        return CTC_E_INVALID_PARAM;
    }

    /* check whether phy interface mode(speed/type) are all the same */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_phy_speed(lchip, phylist, &same));
    if (!same)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] PHY list mode not all the same!\n");
        return CTC_E_INVALID_PARAM;
    }

    /* check whether flexe_shim_id are all the same */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_phy_shim_id_same(phylist, &shim_same));
    if (!shim_same)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] flexe_shim_id are different!\n");
        return CTC_E_INVALID_PARAM;
    }

    /* check whether serdes belong to the same phy */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_serdes_phy_same(lchip, phylist, &serdes_phy_diff));
    if (serdes_phy_diff == FALSE)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] there are serdes belong to the same phy!\n");
        return CTC_E_INVALID_PARAM;
    }
    _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)phylist->serdes_id[0], &logical_serdes_id);
    SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
    CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, logical_serdes_id, &p_serdes));

    if ((CTC_CHIP_SERDES_LG_MODE == p_serdes->mode) || (CTC_CHIP_SERDES_LG_R1_MODE == p_serdes->mode))
    {
        phy_inst_cnt = 1;
    }
    else if ((CTC_CHIP_SERDES_CG_MODE == p_serdes->mode) || (CTC_CHIP_SERDES_CG_R2_MODE == p_serdes->mode))
    {
        phy_inst_cnt = 2;
    }
    else if (CTC_CHIP_SERDES_CCG_R4_MODE == p_serdes->mode)
    {
        phy_inst_cnt = 4;
    }
    else if (CTC_CHIP_SERDES_CDG_R8_MODE == p_serdes->mode)
    {
        phy_inst_cnt = 8;
    }

    /* check whether total instance cnt <= 8 */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_total_inst_cnt(lchip, phylist, phy_inst_cnt, &inst_num_total));
    if (inst_num_total > MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT))
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] oversub happens!\n");
        return CTC_E_INVALID_PARAM;
    }

    /* only LG PHY can set pad enable/disale  */
    if ((CTC_CHIP_SERDES_LG_MODE != p_serdes->mode) && (CTC_CHIP_SERDES_LG_R1_MODE != p_serdes->mode) && (!group_node->pad_en))
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] only LG PHY can set pad enable/disale!\n");
        return CTC_E_INVALID_PARAM;
    }

    /* check whether FlexE shim pad same */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_shim_pad_same(lchip, flexe_shim_id, group_node->pad_en));

    /* check whether lg none fec phy mixed with others */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_dp_fec(lchip, flexe_shim_id, phylist));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_group_client_empty(uint8 lchip, sys_flexe_group_t* group_node, uint8 *p_group_empty)
{
    uint8 group_empty = TRUE;  /* value: whether group has client expect rx-client */
    sys_flexe_client_t* client_node = NULL;
    ctc_slistnode_t* node = NULL;

    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
    {
        client_node = _ctc_container_of(node, sys_flexe_client_t, head);

        if (client_node)
        {
            if (client_node->group_id == group_node->group_id)
            {
                group_empty = FALSE; 
                break;
            }
        }
    }

    if (p_group_empty)
    {
        *p_group_empty = group_empty;
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_bind_group_pc(uint8 lchip, sys_flexe_client_t* p_client_node, uint32 group_id)
{
    sys_flexe_group_t *p_group_node = NULL;

    if (!p_client_node)
    {
        return CTC_E_NOT_INIT;
    }

    /* Check whether client already bind other group */
    if ((SYS_FLEXE_UNUSED_FLAG_U32 != p_client_node->group_id) && (group_id != p_client_node->group_id))
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d already bind with other group!\n", p_client_node->client_id);
        return CTC_E_INVALID_PARAM;
    }

    _sys_tmm_flexe_group_lookup(lchip, group_id, &p_group_node);
    if (!p_group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group ID %d not exist!\n", group_id);
        return CTC_E_NOT_EXIST;
    }

    /* Check whether group bind phylist */
    if (!p_group_node->phy_cnt)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group ID %d not bind phy!\n", group_id);
        return CTC_E_INVALID_PARAM;
    }

    /* check whether client number is configured */
    if (0 == p_client_node->client_number)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d not set client number, CANNOT bind group!\n", p_client_node->client_id);
        return CTC_E_INVALID_PARAM;
    }

    /*Check whether client number is same with other clients in the group */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_client_number_same(lchip, p_client_node->client_number, group_id));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_bind_slot_pc(uint8 lchip, sys_flexe_client_t *client_node, sys_flexe_dir_t dir, ctc_flexe_client_slot_t* p_slot)
{
    uint8 i                 = 0;
    uint8 j                 = 0;
    uint8 t                 = 0;
    uint8 logical_serdes_id = 0;
    uint8 slot_phy_diff     = 1;
    uint8 user_slot_cnt     = 0;
    uint8 mac_tx_en         = 0;
    uint8 mac_rx_en         = 0;
    uint8 asic_inst         = 0;
    uint8 slot_heng         = 0;
    uint8 slot_shu          = 0;
    uint8 group_inst_offset = 0;
    uint8 tmp_shim_chid     = 0;
    uint8 xc_chid           = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;
    sys_flexe_group_t*  client_group_node  = NULL;
    sys_flexe_group_t*  phy_group_node  = NULL;
    sys_flexe_phy_t*    phy_node = NULL;
    sys_flexe_client_t* tmp_client_node = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    if (SYS_FLEXE_UNUSED_FLAG_U32 == client_node->group_id)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client %d has not binded with any group!\n", client_node->client_id);
        return CTC_E_INVALID_CONFIG;
    }

    _sys_tmm_flexe_group_lookup(lchip, client_node->group_id, &client_group_node);
    if (!client_group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group ID %d not exist!\n", client_node->group_id);
        return CTC_E_NOT_EXIST;
    }

    /*calculate the group which serdes belong to */
    for(t = 0; t < p_slot->phy_cnt; t++ )
    {
        _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)p_slot->slot[t].serdes_id, &logical_serdes_id);
        SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
        phy_group_node = _sys_tmm_flexe_group_lookup_by_serdes(lchip, logical_serdes_id);
        if (!phy_group_node)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] phy %d has not added to any FlexE group!\n", p_slot->slot[t].serdes_id);
            return CTC_E_NOT_EXIST;
        }
        else if (client_node->group_id != phy_group_node->group_id)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] phy %d not binded to group %d!\n", p_slot->slot[t].serdes_id, client_node->group_id);
            return CTC_E_INVALID_PARAM;
        }
    }

    /*Check whether slot belongs to different PHY */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_slot_phy_different(lchip, p_slot, &slot_phy_diff));
    if (!slot_phy_diff)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] phys are not all different!\n");
        return CTC_E_INVALID_PARAM;
    }

    /*check whether input slot values are out of range*/
    for(t = 0; t < p_slot->phy_cnt; t++ )
    {
        _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)p_slot->slot[t].serdes_id, &logical_serdes_id);
        SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
        phy_node = _sys_tmm_flexe_get_phy_node(lchip, logical_serdes_id);
        if (!phy_node)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] serdes %d not binded to group %d!\n", p_slot->slot[t].serdes_id, client_node->group_id);
            return CTC_E_NOT_INIT;
        }
        switch (phy_node->pcs_mode)
        {
        case CTC_CHIP_SERDES_LG_MODE:
        case CTC_CHIP_SERDES_LG_R1_MODE:
            for (i = SYS_FLEXE_INSTANCE_SLOT_50G_NUM; i < SYS_FLEXE_INSTANCE_SLOT_400G_NUM; i++)
            {
                if (CTC_BMP_ISSET(p_slot->slot[t].slot_bmp, i))
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Input slot values are out of range!\n");
                    return CTC_E_INVALID_PARAM;
                }
            }
            break;
        case CTC_CHIP_SERDES_CG_MODE:
        case CTC_CHIP_SERDES_CG_R2_MODE:
            for (i = SYS_FLEXE_INSTANCE_SLOT_100G_NUM; i < SYS_FLEXE_INSTANCE_SLOT_400G_NUM; i++)
            {
                if (CTC_BMP_ISSET(p_slot->slot[t].slot_bmp, i))
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Input slot values are out of range!\n");
                    return CTC_E_INVALID_PARAM;
                }
            }
            break;
        case CTC_CHIP_SERDES_CCG_R4_MODE:
            for (i = SYS_FLEXE_INSTANCE_SLOT_200G_NUM; i < SYS_FLEXE_INSTANCE_SLOT_400G_NUM; i++)
            {
                if (CTC_BMP_ISSET(p_slot->slot[t].slot_bmp, i))
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Input slot values are out of range!\n");
                    return CTC_E_INVALID_PARAM;
                }
            }
            break;
        default:
            break;
        }
    }

    /* get user_slot_cnt */
    for (i = 0; i < p_slot->phy_cnt; i++)
    {
        for (j = 0; j < CTC_FLEXE_INSTANCE_SLOT_NUM; j++)
        {
            if (CTC_BMP_ISSET(p_slot->slot[i].slot_bmp, j))
            {
                user_slot_cnt++;
            }
        }
    }
    if (SYS_FLEXE_UNUSED_FLAG_U16 != client_node->mac_id)
    {
        if ((!user_slot_cnt) && (SYS_FLEXE_DIR_TX == dir))
        {
            /* check if mac enable when empty slot */
            CTC_ERROR_RETURN(_sys_tmm_mac_get_flexe_mac_en(lchip, client_node->mac_id, SYS_FLEXE_DIR_TX, &mac_tx_en));
            CTC_ERROR_RETURN(_sys_tmm_mac_get_flexe_mac_en(lchip, client_node->mac_id, SYS_FLEXE_DIR_RX, &mac_rx_en));
            if (mac_tx_en || mac_rx_en)
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client %d must mac disable when empty slot!\n", client_node->client_id);
                return CTC_E_INVALID_PARAM;
            }
        }
        /* check if cross enable, and try to modify slot */
        if (client_node->cross_enable)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client %d must disable L1 cross when empty or resize slot!\n", client_node->client_id);
            return CTC_E_INVALID_PARAM;
        }
        if (SYS_FLEXE_UNUSED_FLAG_U32 != client_node->gport)
        {
            /* check NetTx credit when resize slot */
            CTC_ERROR_RETURN(_sys_tmm_flexe_check_nettx_credit(lchip, client_node, user_slot_cnt));
        }
    }

    /* check whether client is in aps */
    if (SYS_FLEXE_UNUSED_FLAG_U32 != client_node->gport)
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, CTC_MAP_GPORT_TO_LPORT(client_node->gport));
        if (port_attr && port_attr->client_bind_num == 2)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client %d is in aps, CANNOT bind slot!\n", client_node->client_id);
            return CTC_E_INVALID_CONFIG;
        }
    }

    /* check whether the slot belongs to differernt client before and after the switch */
    for(t = 0; t < p_slot->phy_cnt; t++ )
    {
        _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)p_slot->slot[t].serdes_id, &logical_serdes_id);
        phy_node = _sys_tmm_flexe_get_phy_node(lchip, logical_serdes_id);
        if (!phy_node)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] serdes %d not binded to group %d!\n", p_slot->slot[t].serdes_id, client_node->group_id);
            return CTC_E_INVALID_PARAM;
        }
        for (i = 0; i < SYS_FLEXE_INSTANCE_SLOT_400G_NUM; i++)
        {
            if (CTC_BMP_ISSET(p_slot->slot[t].slot_bmp, i))
            {
                slot_heng = i + phy_node->inst_base * MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST);
                (void)_sys_tmm_flexe_slot_heng2shu(lchip, client_group_node, slot_heng, &slot_shu);
                asic_inst = slot_shu / MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST);
                _sys_tmm_flexe_get_group_inst_offset_by_asic_inst(lchip, client_group_node, asic_inst, &group_inst_offset);
                if (SYS_FLEXE_DIR_TX == dir)
                {
                    if (SYS_FLEXE_ACTIVE_A == client_group_node->tx.active)
                    {
                        tmp_shim_chid = client_group_node->tx.dir_inst[group_inst_offset].switch_shim_chid_a[slot_shu%MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST)];
                    }
                    else
                    {
                        tmp_shim_chid = client_group_node->tx.dir_inst[group_inst_offset].switch_shim_chid_b[slot_shu%MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST)];
                    }
                }
                else
                {
                    if (SYS_FLEXE_ACTIVE_A == client_group_node->rx.active)
                    {
                        tmp_shim_chid = client_group_node->rx.dir_inst[group_inst_offset].switch_shim_chid_a[slot_shu%MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST)];
                    }
                    else
                    {
                        tmp_shim_chid = client_group_node->rx.dir_inst[group_inst_offset].switch_shim_chid_b[slot_shu%MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST)];
                    }
                }
                if ((tmp_shim_chid) && (tmp_shim_chid != client_node->shim_chid))
                {
                    xc_chid = SYS_TMM_FLEXE_CLIENT_SHIM_2_XC_CHID(tmp_shim_chid);
                    _sys_tmm_flexe_client_lookup_by_xc_chid(lchip, client_group_node->flexe_shim_id, xc_chid, &tmp_client_node);
                    if (!tmp_client_node)
                    {
                        continue;
                    }
                    if (SYS_FLEXE_DIR_RX == dir)
                    {
                        CTC_ERROR_RETURN(_sys_tmm_flexe_client_force_clear_switch(lchip, client_group_node, tmp_client_node, SYS_FLEXE_DIR_RX));
                    }
                    else
                    {
                        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] [%s] Failed to bind phy %d slot %d to client %d, which is working in client %d\n", \
                            dir?"TX":"RX", p_slot->slot[t].serdes_id, i, client_node->client_id, tmp_client_node->client_id);
                        return CTC_E_INVALID_PARAM;
                    }
                }
            }
        }
    }

    /* check whether the slot has been used when client is different */
    for(t = 0; t < p_slot->phy_cnt; t++ )
    {
        _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)p_slot->slot[t].serdes_id, &logical_serdes_id);
        phy_node = _sys_tmm_flexe_get_phy_node(lchip, logical_serdes_id);
        if (!phy_node)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] serdes %d not binded to group %d!\n", p_slot->slot[t].serdes_id, client_node->group_id);
            return CTC_E_INVALID_PARAM;
        }
        for (i = 0; i < SYS_FLEXE_INSTANCE_SLOT_400G_NUM; i++)
        {
            if (CTC_BMP_ISSET(p_slot->slot[t].slot_bmp, i))
            {
                slot_heng = i + phy_node->inst_base * MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST);
                (void)_sys_tmm_flexe_slot_heng2shu(lchip, client_group_node, slot_heng, &slot_shu);
                asic_inst = slot_shu / MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST);
                _sys_tmm_flexe_get_group_inst_offset_by_asic_inst(lchip, client_group_node, asic_inst, &group_inst_offset);
                if (SYS_FLEXE_DIR_TX == dir)
                {
                    tmp_shim_chid = client_group_node->tx.dir_inst[group_inst_offset].slot_cfg_shim_chid[slot_shu%MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST)];
                }
                else
                {
                    tmp_shim_chid = client_group_node->rx.dir_inst[group_inst_offset].slot_cfg_shim_chid[slot_shu%MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST)];
                }
                if ((tmp_shim_chid) && (tmp_shim_chid != client_node->shim_chid))
                {
                    xc_chid = SYS_TMM_FLEXE_CLIENT_SHIM_2_XC_CHID(tmp_shim_chid);
                    _sys_tmm_flexe_client_lookup_by_xc_chid(lchip, client_group_node->flexe_shim_id, xc_chid, &tmp_client_node);
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] [%s] Failed to bind phy %d slot %d to client %d, which has been used by client %d!\n", \
                        dir?"TX":"RX", p_slot->slot[t].serdes_id, i, client_node->client_id, tmp_client_node->client_id);
                    return CTC_E_INVALID_PARAM;
                }
            }
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_remove_client_pc(uint8 lchip, uint32 client_id)
{
    sys_flexe_client_t* client_node = NULL;

    _sys_tmm_flexe_client_lookup(lchip, client_id, &client_node);
    if (!client_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d not exist!\n", client_id);
        return CTC_E_ENTRY_NOT_EXIST;
    }
    if (SYS_FLEXE_UNUSED_FLAG_U32 != client_node->group_id)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d still bind with group!\n", client_id);
        return CTC_E_INVALID_PARAM;
    }
    if (client_node->bind_oam)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d have bind sc oam session!\n", client_id);
        return CTC_E_IN_USE;
    }
    if (SYS_FLEXE_UNUSED_FLAG_U16 != client_node->mac_id)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d still binded with MAC %d!\n", client_id, client_node->mac_id);
        return CTC_E_NOT_READY;
    }
    if (SYS_FLEXE_UNUSED_FLAG_U8 != client_node->chan_id)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d still binded with chan %d!\n", client_id, client_node->chan_id);
        return CTC_E_NOT_READY;
    }
    if (SYS_FLEXE_UNUSED_FLAG_U32 != client_node->gport)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d still binded with gport %d!\n", client_id, client_node->gport);
        return CTC_E_NOT_READY;
    }

    return CTC_E_NONE;
}

STATIC void
_sys_tmm_flexe_check_value_legal(uint8 lchip, uint8 type, void *arg, void *value_to_be_checked, uint8 *legal)
{
    uint32 val32     = 0;
    uint8  phy_speed = 0;
    uint32 phy_number_max = 0;

    if (!legal)
    {
        return;
    }

    *legal = 1;
    switch (type)
    {
    case SYS_FLEXE_CHECK_GROUP_NUM:
        val32 = *(uint32 *)value_to_be_checked;
        if (val32 > SYS_FLEXE_MAX_GROUP_NUM)  /* write 0 means clear ohram */
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] group_number must be between 0 and 0x%x!\n", SYS_FLEXE_MAX_GROUP_NUM);
            *legal = 0;
        }
        break;
    case SYS_FLEXE_CHECK_PHY_NUM:
        phy_speed = *(uint8 *)arg;
        val32 = *(uint32 *)value_to_be_checked;
        phy_number_max = SYS_FLEXE_MAX_PHY_NUM(phy_speed);
        if (val32 > phy_number_max)   /* write 0 means clear ohram */
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] phy number %u out of range [0-%d]\n", val32, phy_number_max);
            *legal = 0;
        }
        break;
    case SYS_FLEXE_CHECK_CLIENT_NUM:
        val32 = *(uint32 *)value_to_be_checked;
        if (val32 > SYS_FLEXE_MAX_CLIENT_NUM)     /* write 0 means clear ohram */
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] client_number must be between 1 and 0x%x!\n", SYS_FLEXE_MAX_CLIENT_NUM);
            *legal = 0;
        }
        break;
    case SYS_FLEXE_CHECK_BINARY:
        val32 = *(uint32 *)value_to_be_checked;
        if ((0 != val32) && (1 != val32))
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% only value 0 or 1 is supported!\n");
            *legal = 0;
        }
        break;
    default:
        *legal = 0;
        break;
    }
}

STATIC int32
_sys_tmm_flexe_inst_ow_inact_oh_pc(uint8 lchip, uint8 flexe_shim_id, uint8 inst_id, uint8 ohmf_cnt, uint8 oh_field_type, void *p_data)
{
    uint8  i        = 0;
    uint8  tmp_inst_id = 0;
    uint8  shft      = 0;
    uint32 tmp_val32 = 0;
    uint8  valid     = 0;
    uint8  phy_speed = 0;
    uint32 phy_number = 0;
    sys_flexe_group_t *group_node = NULL;
    sys_flexe_phy_t   *p_phy      = NULL;

    group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, flexe_shim_id, inst_id);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] %s @ %d Asic inst %d not belong to any group!\n", __FUNCTION__, __LINE__, inst_id);
        return CTC_E_INVALID_PARAM;
    }

    if ((FLEXE_OH_FIELD_TYPE_FLEXE_MAP != oh_field_type) && (!p_data))
    {
        return CTC_E_INVALID_PARAM;
    }

    /*flexe map*/
    if (FLEXE_OH_FIELD_TYPE_FLEXE_MAP == oh_field_type)
    {
        for(i = 0; i < group_node->inst_cnt; i++)
        {
            tmp_inst_id = group_node->inst_list[i];
            SYS_CONDITION_CONTINUE((SYS_FLEXE_OH_FRAME_NUM_50G != ohmf_cnt) && (tmp_inst_id%2));
            //_sys_tmm_flexe_get_inst_number(lchip, flexe_shim_id, tmp_inst_id, &tmp_inst_number);
            p_phy = _sys_tmm_flexe_phy_lookup_by_inst(lchip, flexe_shim_id, tmp_inst_id);
            SYS_CONDITION_RETURN(!p_phy, CTC_E_NONE);
            SYS_FLEXE_MODE_2_SPEED(p_phy->pcs_mode, phy_speed);
            _sys_tmm_flexe_check_value_legal(lchip, SYS_FLEXE_CHECK_PHY_NUM, (void *)&phy_speed, (void *)&(p_phy->phy_number), &valid);
            return valid ? CTC_E_NONE : CTC_E_INVALID_PARAM;
        }
    }
    else
    {
        switch (oh_field_type)
        {
        case FLEXE_OH_FIELD_TYPE_GROUP_NUM:
            _sys_tmm_flexe_check_value_legal(lchip, SYS_FLEXE_CHECK_GROUP_NUM, NULL, p_data, &valid);
            return valid ? CTC_E_NONE : CTC_E_INVALID_PARAM;
        case FLEXE_OH_FIELD_TYPE_INST_NUM:
            tmp_val32 = *(uint32 *)p_data;
            p_phy = _sys_tmm_flexe_phy_lookup_by_inst(lchip, flexe_shim_id, inst_id);
            SYS_CONDITION_RETURN(!p_phy, CTC_E_NONE);
            SYS_FLEXE_MODE_2_SPEED(p_phy->pcs_mode, phy_speed);
            shft = (CTC_PORT_SPEED_400G == phy_speed) ? 2 : ((CTC_PORT_SPEED_200G == phy_speed) ? 1 : 0);
            phy_number = tmp_val32 >> shft;
            _sys_tmm_flexe_check_value_legal(lchip, SYS_FLEXE_CHECK_PHY_NUM, (void *)&phy_speed, (void *)&phy_number, &valid);
            return valid ? CTC_E_NONE : CTC_E_INVALID_PARAM;
        case FLEXE_OH_FIELD_TYPE_CLIENT_CAL_A:
        case FLEXE_OH_FIELD_TYPE_CLIENT_CAL_B:    
            for (i = 0; i < SYS_FLEXE_OH_MAX_SLOT_PER_INST; i++)
            {
                tmp_val32 = *((uint32*)p_data + i);
                _sys_tmm_flexe_check_value_legal(lchip, SYS_FLEXE_CHECK_CLIENT_NUM, NULL, (void *)&tmp_val32, &valid);
                SYS_CONDITION_BREAK(!valid);
            }
            return valid ? CTC_E_NONE : CTC_E_INVALID_PARAM;
        case FLEXE_OH_FIELD_TYPE_CR:
        case FLEXE_OH_FIELD_TYPE_CA:
        case FLEXE_OH_FIELD_TYPE_C_BIT:
        case FLEXE_OH_FIELD_TYPE_CR_C:
        case FLEXE_OH_FIELD_TYPE_SC:
            _sys_tmm_flexe_check_value_legal(lchip, SYS_FLEXE_CHECK_BINARY, NULL, p_data, &valid);
            return valid ? CTC_E_NONE : CTC_E_INVALID_PARAM;
        default:
            return CTC_E_NONE;
        }
    }

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_check_serdes_bind_group(uint8 lchip, uint16 serdes_id, uint32 *is_bind)
{
    uint8 cs_id              = 0;
    uint8 flexe_en           = 0;
    uint8 flexe_shim_id      = 0;
    uint8 logical_serdes_id  = 0;
    sys_flexe_group_t* group_node = NULL;

    SYS_CONDITION_RETURN(!is_bind, CTC_E_NONE);
    *is_bind = 0;

    flexe_shim_id = SYS_TMM_FLEXE_GET_FLEXE_SHIM(serdes_id);
    if (SYS_FLEXE_UNSUPP == flexe_shim_id)
    {
        *is_bind = 0;
        return CTC_E_NONE;
    }

    SYS_TMM_FLEXE_SERDES_2_CS(serdes_id, cs_id);
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_enable(lchip, cs_id, &flexe_en));
    if (!flexe_en)
    {
        *is_bind = 0;
        return CTC_E_NONE;
    }

    _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)serdes_id, &logical_serdes_id);
    SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
    group_node = _sys_tmm_flexe_group_lookup_by_serdes(lchip, logical_serdes_id);
    if (group_node)
    {
        *is_bind = 1;
    }

    return CTC_E_NONE;
}

int32
_sys_tmm_flexe_check_mac_en_condition(uint8 lchip, uint16 mac_id, sys_flexe_dir_t dir, uint8 enable)
{
    return CTC_E_NONE;
}

STATIC uint8
_sys_tmm_flexe_is_bind_first_phy(uint8 lchip, uint8 shim_id)
{
    uint8 is_first = TRUE;
    uint8 base_serdes_id = 0;
    uint8 i = 0;
    sys_flexe_group_t* p_group_node = NULL;

    SYS_FLEXE_SHIM_2_BASE_LOGIC_SERDES(shim_id, base_serdes_id);
    for(i = base_serdes_id; i < base_serdes_id + TMM_MAX_SERDES_NUM_PER_CS*2; i++)
    {
        p_group_node = _sys_tmm_flexe_group_lookup_by_serdes(lchip, i);
        if (p_group_node)
        {
            is_first = FALSE;
            break;
        }
    }

    return is_first;
}

STATIC int32
_sys_tmm_flexe_check_flexe_cs_used(uint8 lchip, uint8 cs_id, uint8 *p_cs_used)
{
    uint8 i = 0;
    uint8 cs_loop = 0;
    uint8 cs_used = 0;
    uint16 mac_base = 0;
    sys_flexe_group_t* group_node = NULL;
    sys_flexe_client_t* client_node = NULL;
    ctc_slistnode_t* node = NULL;

    /* Step 1, check CS PHY is used by FlexE group or not */
    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->group_list, node)
    {
        group_node = _ctc_container_of(node, sys_flexe_group_t, head);
        SYS_CONDITION_CONTINUE(!group_node || !group_node->phy_cnt);

        for (i = 0; i < group_node->phy_cnt; i++)
        {
            SYS_TMM_FLEXE_SERDES_2_CS(group_node->phy_list[i].logical_serdes_base, cs_loop);
            if (cs_id == cs_loop)
            {
                cs_used = 1;
                break;
            }
        }
        if (cs_used)
            break;
    }

    /* Step 2, check CS MAC is used by FlexE client or not */
    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
    {
        client_node = _ctc_container_of(node, sys_flexe_client_t, head);
        mac_base = SYS_TMM_MAX_MAC_NUM_PER_TXQM*(cs_id%2);
        mac_base += (cs_id < 2) ? 80 : 240;
        if ((client_node->mac_id >= mac_base) 
            && (client_node->mac_id < (mac_base + SYS_TMM_MAX_MAC_NUM_PER_TXQM)))
        {
            cs_used = 1;
            break;
        }
        if (cs_used)
            break;
    }

    *p_cs_used = cs_used;
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_group_phy_number_same(uint8 lchip, sys_flexe_group_t *group_node, uint8 logical_serdes_base, uint32 phy_number)
{
    uint8 i = 0;

    if (0 == phy_number)
    {
        return CTC_E_NONE;
    }

    for (i = 0; i < group_node->phy_cnt; i++)
    {
        SYS_CONDITION_CONTINUE(logical_serdes_base == group_node->phy_list[i].logical_serdes_base);
        if (phy_number == group_node->phy_list[i].phy_number)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] PHY number %d is used by other PHY in group %d!\n", \
                phy_number, group_node->group_id);
            return CTC_E_INVALID_PARAM;
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_group_phy_number_sequence(uint8 lchip, sys_flexe_group_t *group_node, uint8 logical_serdes_base, uint32 phy_number)
{
    uint8 i = 0;
    uint8 phy_index = 0;

    if (0 == phy_number)
    {
        return CTC_E_NONE;
    }

    for (i = 0; i < group_node->phy_cnt; i++)
    {
        if (logical_serdes_base == group_node->phy_list[i].logical_serdes_base)
        {
            phy_index = i;
            break;
        }
    }

    if (((phy_index < (group_node->phy_cnt-1)) && (group_node->phy_list[phy_index+1].phy_number) && (phy_number > group_node->phy_list[phy_index+1].phy_number))\
        || ((0 < phy_index) && (group_node->phy_list[phy_index-1].phy_number > phy_number)))
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] PHY number should be from small to large in phylist!\n");
        return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_group_switch_status(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, uint8 target_table)
{
    uint32  table = 0;
    uint32  read_cnt = 0;

    while (1)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_table(lchip, group_node, dir, &table));
        read_cnt++;

        if (target_table == table) 
        {
            sal_task_sleep(30);
            /* check abnormal intr for 2 times */
            (void)_ctc_tmm_dkit_check_abnormal_intr(lchip, 0);
            (void)_ctc_tmm_dkit_check_abnormal_intr(lchip, 0);
            break;
        }

        /* sleep 1ms after a round*/
        sal_task_sleep(1);
        /* report error after 20 round*/
        if (read_cnt >= 50)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group id %d, dir %s, hw table switch fail! target_table: %d\n", group_node->group_id, dir?"TX":"RX", target_table);
            return CTC_E_HW_FAIL;
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_group_manual_table(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, uint32 *p_val)
{
    uint32  table = 0;
    uint32  read_cnt = 0;

    while (1)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_table(lchip, group_node, dir, &table));
        read_cnt++;

        if ((SYS_FLEXE_ACTIVE_A == table) || (SYS_FLEXE_ACTIVE_B == table))
        {
            break;
        }

        /* sleep 1ms after a round*/
        sal_task_sleep(1);
        /* report error after 20 round*/
        if (read_cnt >= 50)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group id %d, dir %s, get hw table fail!\n", group_node->group_id, dir?"TX":"RX");
            return CTC_E_HW_FAIL;
        }
    }

    if (p_val)
    {
        *p_val = table;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_check_ohram_alarm(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint8 i                 = 0;
    uint8 speed_mode        = 0;
    uint32 asic_inst        = 0;

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        asic_inst = group_node->inst_list[i];
        _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);
        if (((CTC_PORT_SPEED_50G != speed_mode) && (0 == asic_inst%2)) || (CTC_PORT_SPEED_50G == speed_mode))
        {
            _sys_tmm_flexe_alarm_mismatch(lchip, asic_inst, group_node->flexe_shim_id);
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_ohram_alarm(uint8 lchip, sys_flexe_group_t* group_node, uint8* p_alarm)
{
    uint8 i                     = 0;
    uint8 flag                  = 0;
    uint8 inst_offset           = 0;
    uint8 user_inst_cnt         = 0;
    uint8 speed_mode            = 0;
    sys_flexe_phy_t*   phy_node = NULL;

    if (0 == group_node->phy_cnt)
    {
        *p_alarm = 0;
        return CTC_E_NONE;
    }

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);
    switch (speed_mode)
    {
        case CTC_PORT_SPEED_50G:
        case CTC_PORT_SPEED_100G:
            user_inst_cnt = 1;
            break;
        case CTC_PORT_SPEED_200G:
            user_inst_cnt = 2;
            break;
        case CTC_PORT_SPEED_400G:
            user_inst_cnt = 4;
            break;
        default:
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] Unsupported speed mode %d\n", speed_mode);
            return CTC_E_INVALID_PARAM;
    }

    /* check group number/instance number/FlexE map mismatch */
    for (i = 0; i < group_node->phy_cnt; i++)
    {
        phy_node = &group_node->phy_list[i];
        for (inst_offset = 0; inst_offset < user_inst_cnt; inst_offset++)
        {
            if ((CTC_IS_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_GRP_NUM_MISMATCH)) ||\
                (CTC_IS_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_INST_NUM_MISMATCH)) ||\
                (CTC_IS_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_MAP_MISMATCH)))
            {
                *p_alarm = 1;
                flag = 1;
                break;
            }
        }
        if (1 == flag)
        {
            break;
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_group_phy_up(uint8 lchip, sys_flexe_group_t* group_node, uint8 *p_link_stat)
{
    int32 i = 0;
    uint32  link_stat = 0;  /*1-up  0-down*/
    sys_datapath_serdes_info_t* p_serdes  = NULL;
    sys_flexe_phy_t*   p_phy = NULL;

    for (i = 0; i < group_node->phy_cnt; i++)
    {
        p_phy = &group_node->phy_list[i];

        CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, p_phy->logical_serdes_base, &p_serdes));
        SYS_CONDITION_RETURN(SYS_USW_MAX_PORT_NUM_PER_CHIP <= p_serdes->lport, CTC_E_INVALID_PARAM);
        CTC_ERROR_RETURN(_sys_tmm_mac_get_pcs_link_status(lchip, p_serdes->lport, &link_stat));
        if(!link_stat)
        {
            break;
        }
    }
    if (p_link_stat)
    {
        *p_link_stat = link_stat;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_cross_pc(uint8 lchip, ctc_flexe_cross_t* p_cross, uint8 *p_is_ret)
{
    uint8  is_ret = 0;
    uint32  tx_cfg_src = FALSE;
    uint32  rx_cfg_src = FALSE;
    uint32  tx_act_src = FALSE;
    uint32  rx_act_src = FALSE;
    uint32  tx_cfg_dest = FALSE;
    uint32  rx_cfg_dest = FALSE;
    uint32  tx_act_dest = FALSE;
    uint32  rx_act_dest = FALSE;
    sys_flexe_client_t* src_client_node = NULL;
    sys_flexe_client_t* dest_client_node = NULL;
    sys_flexe_group_t* src_group_node = NULL;
    sys_flexe_group_t* dest_group_node = NULL;

    _sys_tmm_flexe_client_lookup(lchip, p_cross->client_id, &src_client_node);
    if (!src_client_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d not exist!\n", p_cross->client_id);
        return CTC_E_NOT_EXIST;
    }
    _sys_tmm_flexe_group_lookup(lchip, src_client_node->group_id, &src_group_node);
    if (!src_group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client %d not binded to any group, CANNOT config L1 cross-connect!\n", p_cross->client_id);
        return CTC_E_INVALID_CONFIG;
    }
    _sys_tmm_flexe_client_lookup(lchip, p_cross->dest_client_id, &dest_client_node);
    if (!dest_client_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] dest client ID %d not exist!\n", p_cross->dest_client_id);
        return CTC_E_NOT_EXIST;
    }
    _sys_tmm_flexe_group_lookup(lchip, dest_client_node->group_id, &dest_group_node);
    if (!dest_group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client %d not binded to any group, CANNOT config L1 cross-connect!\n", p_cross->dest_client_id);
        return CTC_E_INVALID_CONFIG;
    }
    /* check whether client id is same */
    if (src_client_node->client_id ==  dest_client_node->client_id)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] L1 cross src client and dest client CANNOT be the same!\n");
        return CTC_E_INVALID_PARAM;
    }

    if (!p_cross->enable)  /* param check for cross disable only */
    {
        if (src_client_node->cross_enable)   /* SRC is enabled */
        {
            if (dest_client_node->cross_enable)   /* Dest is enabled */
            {
                if ((src_client_node->cross_client_id == p_cross->dest_client_id) && (dest_client_node->cross_client_id == p_cross->client_id))
                {
                    /* param check pass! DO NOTHING*/
                }
                else
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Src client %d and dest client %d are not L1 cross-connected with each other!\n", \
                        src_client_node->client_id, dest_client_node->client_id);
                    return CTC_E_INVALID_PARAM;
                }
            }
            else  /* Dest is disabled */
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Src client %d L1 cross-connnect is enable, while dest client %d is disable, Pls check your param!\n", \
                    p_cross->client_id, p_cross->dest_client_id);
                return CTC_E_INVALID_PARAM;
            }
        }
        else   /* SRC is disabled */
        {
            if (dest_client_node->cross_enable) /* Dest is enabled */
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Src client %d L1 cross-connnect is disable, while dest client %d is enable, Pls check your param!\n", \
                    p_cross->client_id, p_cross->dest_client_id);
                return CTC_E_INVALID_PARAM;
            }
            else  /* Dest is disabled */
            {
                is_ret = 1;  /* cross-connect API will DO NOTHING */
            }
        }

        if (dest_client_node->cross_enable)   /* Dest is enabled */
        {
            if (src_client_node->cross_enable)   /* SRC is enabled */
            {
                if ((src_client_node->cross_client_id == p_cross->dest_client_id) && (dest_client_node->cross_client_id == p_cross->client_id))
                {
                    /* param check pass! DO NOTHING*/
                }
                else
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Src client %d and dest client %d are not L1 cross-connected with each other!\n", \
                        src_client_node->client_id, dest_client_node->client_id);
                    return CTC_E_INVALID_PARAM;
                }
            }
            else  /* SRC is disabled */
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Src client %d L1 cross-connnect is disable, while dest client %d is enable, Pls check your param!\n", \
                    p_cross->client_id, p_cross->dest_client_id);
                return CTC_E_INVALID_PARAM;
            }
        }
        else   /* Dest is disabled */
        {
            if (src_client_node->cross_enable) /* SRC is enabled */
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Src client %d L1 cross-connnect is enable, while dest client %d is disable, Pls check your param!\n", \
                    p_cross->client_id, p_cross->dest_client_id);
                return CTC_E_INVALID_PARAM;
            }
            else  /* SRC is disabled */
            {
                is_ret = 1;  /* cross-connect API will DO NOTHING */
            }
        }
    }
    else  /* param check for cross enable only */
    {
        if (src_client_node->cross_enable)   /* SRC is enabled */
        {
            if (dest_client_node->cross_enable)   /* Dest is enabled */
            {
                if ((src_client_node->cross_client_id == p_cross->dest_client_id) && (dest_client_node->cross_client_id == p_cross->client_id))
                {
                    is_ret = 1;   /* cross-connect API will DO NOTHING */
                }
                else
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Src client %d and dest client %d are all L1 cross-connected, but not with each other!\n", \
                        src_client_node->client_id, dest_client_node->client_id);
                    return CTC_E_INVALID_CONFIG;
                }
            }
            else  /* Dest is disabled */
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Src client %d L1 cross-connnect is enable, while dest client %d is disable, Pls check your param!\n", \
                    p_cross->client_id, p_cross->dest_client_id);
                return CTC_E_INVALID_PARAM;
            }
        }
        else   /* SRC is disabled */
        {
            if (dest_client_node->cross_enable) /* Dest is enabled */
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Src client %d L1 cross-connnect is disable, while dest client %d is enable, Pls check your param!\n", \
                    p_cross->client_id, p_cross->dest_client_id);
                return CTC_E_INVALID_PARAM;
            }
            else  /* Dest is disabled */
            {
                /* param check pass! DO NOTHING*/
            }
        }

        if (dest_client_node->cross_enable)   /* Dest is enabled */
        {
            if (src_client_node->cross_enable)   /* SRC is enabled */
            {
                if ((src_client_node->cross_client_id == p_cross->dest_client_id) && (dest_client_node->cross_client_id == p_cross->client_id))
                {
                    is_ret = 1;   /* cross-connect API will DO NOTHING */
                }
                else
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Src client %d and dest client %d are all L1 cross-connected, but not with each other!\n", \
                        src_client_node->client_id, dest_client_node->client_id);
                    return CTC_E_INVALID_CONFIG;
                }
            }
            else  /* SRC is disabled */
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Src client %d L1 cross-connnect is disable, while dest client %d is enable, Pls check your param!\n", \
                    p_cross->client_id, p_cross->dest_client_id);
                return CTC_E_INVALID_PARAM;
            }
        }
        else   /* Dest is disabled */
        {
            if (src_client_node->cross_enable) /* SRC is enabled */
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Src client %d L1 cross-connnect is enable, while dest client %d is disable, Pls check your param!\n", \
                    p_cross->client_id, p_cross->dest_client_id);
                return CTC_E_INVALID_PARAM;
            }
            else  /* SRC is disabled */
            {
                /* param check pass! DO NOTHING*/
            }
        }
    }

    if (p_cross->enable)  /* param check for cross enable only */
    {
        if ((SYS_FLEXE_GROUP_TX_IDLE != src_group_node->tx.crac_state) || (SYS_FLEXE_GROUP_RX_IDLE != src_group_node->rx.crac_state))
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client %d group %d is still in switch progress, CANNOT config L1 cross-connect!\n", \
                p_cross->client_id, src_client_node->group_id);
            return CTC_E_INVALID_PARAM;
        }
        if ((SYS_FLEXE_GROUP_TX_IDLE != dest_group_node->tx.crac_state) || (SYS_FLEXE_GROUP_RX_IDLE != dest_group_node->rx.crac_state))
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client %d group %d is still in switch progress, CANNOT config L1 cross-connect!\n", \
                p_cross->dest_client_id, dest_client_node->group_id);
            return CTC_E_INVALID_PARAM;
        }

        /* check whether client has been bind port */
        if (src_client_node->gport != SYS_FLEXE_UNUSED_FLAG_U32)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Src client %d has binded port %d, CANNOT config L1 cross-connect!\n", src_client_node->client_id, src_client_node->gport);
            return CTC_E_INVALID_PARAM;
        }
        if (dest_client_node->gport != SYS_FLEXE_UNUSED_FLAG_U32)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Dest client %d has binded port %d, CANNOT config L1 cross-connect!\n", dest_client_node->client_id, dest_client_node->gport);
            return CTC_E_INVALID_PARAM;
        }

        _sys_tmm_flexe_get_client_speed_val(lchip, src_client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_CFG_FLAG, &tx_cfg_src);
        _sys_tmm_flexe_get_client_speed_val(lchip, src_client_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_CFG_FLAG, &rx_cfg_src);
        _sys_tmm_flexe_get_client_speed_val(lchip, src_client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_ACTIVE_FLAG, &tx_act_src);
        _sys_tmm_flexe_get_client_speed_val(lchip, src_client_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_ACTIVE_FLAG, &rx_act_src);
        _sys_tmm_flexe_get_client_speed_val(lchip, dest_client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_CFG_FLAG, &tx_cfg_dest);
        _sys_tmm_flexe_get_client_speed_val(lchip, dest_client_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_CFG_FLAG, &rx_cfg_dest);
        _sys_tmm_flexe_get_client_speed_val(lchip, dest_client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_ACTIVE_FLAG, &tx_act_dest);
        _sys_tmm_flexe_get_client_speed_val(lchip, dest_client_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_ACTIVE_FLAG, &rx_act_dest);

        /* check whether client has slot */
        if (!tx_cfg_src || !rx_cfg_src || !tx_act_src || !rx_act_src)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Src client %d slot is empty, CANNOT config L1 cross-connect!\n", src_client_node->client_id);
            return CTC_E_INVALID_PARAM;
        }
        if (!tx_cfg_dest || !rx_cfg_dest || !tx_act_dest || !rx_act_dest)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Dest client %d slot is empty, CANNOT config L1 cross-connect!\n", dest_client_node->client_id);
            return CTC_E_INVALID_PARAM;
        }

        /* check whether client speed is same */
        if ((tx_act_src != tx_act_dest) || (rx_act_src != rx_act_dest))
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Src client working speed is different from dest client, CANNOT config L1 cross-connect!\n");
            return CTC_E_INVALID_PARAM;
        }

        /* check whether client backup speed is same with current speed */
        if ((tx_cfg_src != tx_act_src) || (rx_cfg_src != rx_act_src))
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Src client %d working speed is different from backup speed, CANNOT config L1 cross-connect!\n", \
                src_client_node->client_id);
            return CTC_E_INVALID_PARAM;
        }
        if ((tx_cfg_dest != tx_act_dest) || (rx_cfg_dest != rx_act_dest))
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Dest client %d working speed is different from backup speed, CANNOT config L1 cross-connect!\n", \
                dest_client_node->client_id);
            return CTC_E_INVALID_PARAM;
        }
    }

    if (p_is_ret)
    {
        *p_is_ret = is_ret;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_group_ohlock_unmask(uint8 lchip, sys_flexe_group_t* group_node, uint8 *p_unmask)
{
    uint8 i = 0;
    uint8 asic_inst = 0;
    uint8 inst_bmp = 0;
    uint8 mask = 0;  /* 0- do  1- not do */

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        asic_inst = group_node->inst_list[i];
        inst_bmp |= (1 << asic_inst);
    }

    CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_intr_op_get(lchip, group_node->flexe_shim_id, inst_bmp, SYS_FLEXE_MGR_INTR_OHLOCK, INTR_INDEX_MASK_SET, &mask));

    if (p_unmask)
    {
        *p_unmask = mask ? 0 : 1;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_check_phy_ohlock_unmask(uint8 lchip, sys_flexe_group_t *group_node, uint8 logical_serdes_id, uint8 *p_unmask)
{
    uint8 inst_bmp = 0;
    uint8 mask = 0;  /* 0- do  1- not do */

    _sys_tmm_flexe_get_inst_bmp_by_serdes(lchip, group_node, logical_serdes_id, &inst_bmp);

    CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_intr_op_get(lchip, group_node->flexe_shim_id, inst_bmp, SYS_FLEXE_MGR_INTR_OHLOCK, INTR_INDEX_MASK_SET, &mask));

    if (p_unmask)
    {
        *p_unmask = mask ? 0 : 1;
    }

    return CTC_E_NONE;
}


STATIC int32
_sys_tmm_flexe_check_group_working_backup_slot_diff(uint8 lchip, sys_flexe_group_t* group_node, uint8 *p_diff)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 diff = 0;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            /* tx */
            if (SYS_FLEXE_ACTIVE_A == group_node->tx.active)
            {
                if (group_node->tx.dir_inst[i].slot_cfg_shim_chid[j] != group_node->tx.dir_inst[i].switch_shim_chid_a[j])
                {
                    diff = 1;
                    break;
                }
            }
            else
            {
                if (group_node->tx.dir_inst[i].slot_cfg_shim_chid[j] != group_node->tx.dir_inst[i].switch_shim_chid_b[j])
                {
                    diff = 1;
                    break;
                }
            }
            /* rx */
            if (SYS_FLEXE_ACTIVE_A == group_node->rx.active)
            {
                if (group_node->rx.dir_inst[i].slot_cfg_shim_chid[j] != group_node->rx.dir_inst[i].switch_shim_chid_a[j])
                {
                    diff = 1;
                    break;
                }
            }
            else
            {
                if (group_node->rx.dir_inst[i].slot_cfg_shim_chid[j] != group_node->rx.dir_inst[i].switch_shim_chid_b[j])
                {
                    diff = 1;
                    break;
                }
            }
        }
        if (1 == diff)
        {
            break;
        }
    }

    if (p_diff)
    {
        *p_diff = diff;
    }

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_check_client_match(uint8 lchip, sys_flexe_client_t *client_node, uint8 *p_match)
{
    uint8 i                     = 0;
    uint8 j                     = 0;
    uint8 match                 = 1;
    uint8 flag                  = 0;
    uint8 slot_heng             = 0;
    uint8 slot_shu              = 0;
    uint8 logical_serdes_id     = 0;
    ctc_flexe_client_slot_t client_slot;
    ctc_flexe_slot_bmp_t slot_phy[8];
    uint32 oh_client_slot[SYS_FLEXE_MAX_INST_CNT][SYS_FLEXE_INSTANCE_SLOT_50G_NUM] = {{0}};
    uint32 active_client_slot[SYS_FLEXE_MAX_INST_CNT][SYS_FLEXE_INSTANCE_SLOT_50G_NUM] = {{0}};

    sys_flexe_group_t  *group_node = NULL;
    sys_flexe_phy_t*    phy_node = NULL;

    _sys_tmm_flexe_group_lookup(lchip, client_node->group_id, &group_node);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group ID %d not exist!\n", client_node->group_id);
        return CTC_E_NOT_EXIST;
    }

    sal_memset(&client_slot, 0, sizeof(ctc_flexe_client_slot_t));
    sal_memset(slot_phy, 0, 8 * sizeof(ctc_flexe_slot_bmp_t));
    sal_memset(oh_client_slot, 0, sizeof(oh_client_slot));
    sal_memset(active_client_slot, 0, sizeof(active_client_slot));

    client_slot.slot = slot_phy;

    /* get client slot from ohram */
    CTC_ERROR_RETURN(_sys_tmm_flexe_client_rx_slot_calc(lchip, group_node, client_node, SYS_FLEXE_ACTIVE_FLAG, TRUE, &client_slot));

    /* transfer client slot from ctc_flexe_client_slot_t to array */
    for (i = 0; i < client_slot.phy_cnt; i++)
    {
        _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)client_slot.slot[i].serdes_id, &logical_serdes_id);
        SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
        phy_node = _sys_tmm_flexe_get_phy_node(lchip, logical_serdes_id);
        if (!phy_node)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] logical_serdes %d not binded to any group!\n", logical_serdes_id);
            return CTC_E_NOT_INIT;
        }

        for (j = 0; j < SYS_FLEXE_INSTANCE_SLOT_400G_NUM; j++)
        {
            if (CTC_BMP_ISSET(client_slot.slot[i].slot_bmp, j))
            {
                slot_heng = phy_node->inst_base * SYS_FLEXE_INSTANCE_SLOT_50G_NUM + j;
                (void)_sys_tmm_flexe_slot_heng2shu(lchip, group_node, slot_heng, &slot_shu);
                oh_client_slot[slot_shu/SYS_FLEXE_INSTANCE_SLOT_50G_NUM][slot_shu%SYS_FLEXE_INSTANCE_SLOT_50G_NUM] = 1;
            }
        }
    }

    /* get rx active group client slot */
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_hw_client_slot(lchip, group_node, client_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_ACTIVE_FLAG, active_client_slot));

    /* compare oh slot and active slot */
    for (i = 0; i < SYS_FLEXE_MAX_INST_CNT; i++)
    {
        for (j = 0; j < SYS_FLEXE_INSTANCE_SLOT_50G_NUM; j++)
        {
            if (oh_client_slot[i][j] != active_client_slot[i][j])
            {
                match = 0;
                flag = 1;
                break;
            }
        }
        if (1 == flag)
        {
            break;
        }
    }

    if (p_match)
    {
        *p_match = match;
    }

    return CTC_E_NONE;
}

#define ____FLEXE_MIDDLEWARE____

void
_sys_tmm_flexe_intr_cb(uint8 lchip, ctc_flexe_status_event_t* flexe_event)
{
    uint8 gchip = 0;
    CTC_INTERRUPT_EVENT_FUNC cb = NULL;

    (void)sys_usw_get_gchip_id(lchip, &gchip);

    /* get user cb function*/
    (void)sys_usw_interrupt_get_event_cb(lchip, CTC_EVENT_FLEXE_STATUS, &cb);

    if (cb)
    {
        /* cb*/
        (void)cb(gchip, flexe_event);
    }
}

STATIC int32
sys_tmm_flexe_remove_client_node(uint8 lchip, sys_flexe_client_t *client_node)
{
    ctc_slistnode_t        *node = NULL;

    _sys_tmm_flexe_init_client_ds(lchip, client_node);

    node = &(client_node->head);
    ctc_slist_delete_node(p_usw_flexe_master[lchip]->client_list, node);
    mem_free(client_node);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_FLEXE, SYS_WB_APPID_FLEXE_SUBID_CLIENT, 1);

    return CTC_E_NONE;
}

int32
_sys_tmm_flexe_get_phy_status_by_lport(uint8 lchip, uint16 lport, sys_datapath_lport_attr_t* port_attr, uint8 status_type, uint8* p_status)
{
    uint8 i                 = 0;
    uint8 inst_id           = 0;
    uint8 inst_cnt          = 0;
    uint8 status            = 0;
    uint8 rpf               = 0;
    uint8 logical_serdes_id = 0;
    sys_flexe_group_t *group_node = NULL;
    sys_flexe_phy_t* phy_node = NULL;

    _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, port_attr->multi_serdes_id[0], &logical_serdes_id);

    group_node = _sys_tmm_flexe_group_lookup_by_serdes(lchip, logical_serdes_id);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] serdes_id %d has not added to any FlexE group!\n", port_attr->multi_serdes_id[0]);
        *p_status = 0;
        return CTC_E_NONE;
    }
    phy_node = (sys_flexe_phy_t *)_sys_tmm_flexe_get_phy_node(lchip, logical_serdes_id);
    if (!phy_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] SerDes ID %d is not used by any group\n", port_attr->multi_serdes_id[0]);
        *p_status = 0;
        return CTC_E_NONE;
    }
    switch (phy_node->pcs_mode)
    {
    case CTC_CHIP_SERDES_LG_MODE:
    case CTC_CHIP_SERDES_LG_R1_MODE:
        inst_cnt = 1;
        break;
    case CTC_CHIP_SERDES_CG_MODE:
    case CTC_CHIP_SERDES_CG_R2_MODE:
        inst_cnt = 2;
        break;
    case CTC_CHIP_SERDES_CCG_R4_MODE:
        inst_cnt = 4;
        break;
    case CTC_CHIP_SERDES_CDG_R8_MODE:
        inst_cnt = 8;
        break;
    default:
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] Unsupported PCS mode %d \n", phy_node->pcs_mode);
        *p_status = 0;
        return CTC_E_NONE;
    }

    for (i = 0; i < inst_cnt; i++)
    {
        inst_id = phy_node->inst_base + i;
        if (SYS_FLEXE_PCS_LINK == status_type)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_get_inst_pcs_link_status(lchip, group_node->flexe_shim_id, inst_id, &status));
        }
        else if (SYS_FLEXE_OH_LOCK == status_type)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_get_inst_ohlock(lchip, group_node->flexe_shim_id, inst_id, &status));
        }
        else if (SYS_FLEXE_OHMF_LOCK == status_type)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_get_inst_ohmflock(lchip, group_node->flexe_shim_id, inst_id, &status));
        }
        else if (SYS_FLEXE_PAD_LOCK == status_type)
        {
            if (((CTC_CHIP_SERDES_LG_MODE == phy_node->pcs_mode) || (CTC_CHIP_SERDES_LG_R1_MODE == phy_node->pcs_mode)) && \
                (1 == group_node->pad_en))
            {
                CTC_ERROR_RETURN(_sys_tmm_flexe_clear_inst_ohlock(lchip, group_node->flexe_shim_id, inst_id));
                CTC_ERROR_RETURN(_sys_tmm_flexe_get_inst_padlock(lchip, group_node->flexe_shim_id, inst_id, &status));
            }
            else
            {
                status = 1;
            }
        }
        else
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_clear_inst_ohlock(lchip, group_node->flexe_shim_id, inst_id));
            CTC_ERROR_RETURN(_sys_tmm_flexe_get_inst_rpf(lchip, group_node->flexe_shim_id, phy_node->inst_base, &rpf));
            status = rpf ? 0 : 1;
        }
        if (!status)
        {
            *p_status = 0;
            return CTC_E_NONE;
        }
    }

    *p_status = 1;
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_set_port_attr(uint8 lchip, sys_flexe_client_t* client_node, uint16 lport)
{
    uint8 slot_cnt = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;

    port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
    if (!port_attr)
    {
        return CTC_E_NO_MEMORY;
    }

    CTC_ERROR_RETURN(_sys_tmm_flexe_get_client_slot_cnt(lchip, client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_INACTIVE_FLAG, &slot_cnt));

    if (0 == port_attr->client_bind_num)
    {
        port_attr->chan_id            = client_node->chan_id;
        port_attr->mac_id             = client_node->mac_id;
        port_attr->port_type          = SYS_DMPS_RSV_PORT;
        if (SYS_FLEXE_UNUSED_FLAG_U16 != client_node->mac_id)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_check_nettx_credit(lchip, client_node, slot_cnt));
            port_attr->port_type          = SYS_DMPS_NETWORK_PORT;
            port_attr->internal_mac_idx   = SYS_TMM_GET_MACID_PER_TXQM(port_attr->mac_id);
            port_attr->txqm_id            = port_attr->mac_id / SYS_TMM_MAX_MAC_NUM_PER_TXQM;
        }
        port_attr->slice_id           = 0;
        port_attr->serdes_num         = 0;
        port_attr->pcs_mode           = CTC_CHIP_SERDES_NONE_MODE;
        port_attr->serdes_id          = SYS_TMM_USELESS_ID8;
        port_attr->is_serdes_dyn      = 0;
        port_attr->is_first           = 0;
        port_attr->flag               = 0;
        port_attr->interface_type     = CTC_PORT_IF_FLEXE;
        port_attr->an_fec             = 0;
        port_attr->code_err_count     = 0;
        port_attr->pcs_reset_en       = 0;
        port_attr->pcs_idx            = SYS_TMM_USELESS_ID8;
        port_attr->xpipe_en           = CTC_PORT_XPIPE_TYPE_0;
        port_attr->pmac_id            = SYS_TMM_USELESS_ID16;
        port_attr->emac_id            = SYS_TMM_USELESS_ID16;
        port_attr->pmac_chanid        = SYS_TMM_USELESS_ID8;
        port_attr->emac_chanid        = SYS_TMM_USELESS_ID8;
        port_attr->mutex_flag         = SYS_TMM_USELESS_ID8;
        port_attr->q_credit           = 0;
        port_attr->an_done_opr        = FALSE;
        port_attr->an_ability.base_ability0 = SYS_TMM_USELESS_ID32;
        port_attr->an_ability.base_ability1 = SYS_TMM_USELESS_ID32;
        port_attr->an_ability.np0_ability0  = SYS_TMM_USELESS_ID32;
        port_attr->an_ability.np0_ability1  = SYS_TMM_USELESS_ID32;
        port_attr->an_ability.np1_ability0  = SYS_TMM_USELESS_ID32;
        port_attr->an_ability.np1_ability1  = SYS_TMM_USELESS_ID32;
        port_attr->speed_value        = 0;
        port_attr->mac_id_reserve     = SYS_TMM_USELESS_ID16;
        port_attr->flexe_mactx_encfg  = 0;
        port_attr->flexe_macrx_encfg  = 0;
        port_attr->lt_done_num        = 0;
        port_attr->flexe_en           = 0;
        port_attr->flexe_client       = client_node->client_id;
        port_attr->flexe_client_aps   = 0;
    }
    else
    {
        port_attr->mac_id_aps = client_node->mac_id;
        port_attr->flexe_client_aps   = client_node->client_id;
    }

    FLEXE_DBG_PRINTF("[FlexE] Client %d alloc lport %d chan %d mac %d txqm %d\n", client_node->client_id,\
        lport, port_attr->chan_id, (0 == port_attr->client_bind_num)?(port_attr->mac_id):(port_attr->mac_id_aps), port_attr->txqm_id);

    return CTC_E_NONE;
}

STATIC uint32
_sys_tmm_flexe_mac_get_eth_config_val(uint8 lchip, uint8 serdes_mode, uint8 fec_type, uint8 item)
{
    uint32 mode_fec                      = MAX_MODE_FEC;
    uint32 value                         = 0;

    if(CTC_PORT_FEC_TYPE_NONE != fec_type)
    {
        mode_fec = g_mode_with_fec_map[serdes_mode][FEC_TYPE_NORMALIZE(fec_type)];
    }

    /*get fec value or non-fec*/
    value = (CTC_PORT_FEC_TYPE_NONE == fec_type) ? g_mcmac_mode_value_map[item][serdes_mode] : g_mcmac_fec_value_map[item][mode_fec];

    return value;
}

STATIC int32
_sys_tmm_flexe_read_ohram(uint8 lchip, uint8 flexe_shim_id, uint32 frame_id, uint8 asic_inst, 
                                          uint32 p_val[FLEXE_OH_FIELD_MAX], sys_flexe_dir_t dir)
{
    uint8  i         = 0;
    uint8  oh_field  = 0;
    uint32 tbl_id    = 0;
    uint32 entry     = 0;
    uint32 index     = 0;
    uint32 cmd       = 0;
    uint32 val32_raw = 0;
    uint32 mask      = 0;
    uint32 start_bit = 0;
    RxOhFrameRamInst0_m  oh_ram;

    if (flexe_shim_id > 1)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] invalid flexe shim id %d!\n", flexe_shim_id);
        return CTC_E_INVALID_PARAM;
    }

    tbl_id = (SYS_FLEXE_DIR_RX == dir) ? 
             (RxOhFrameRamInst0_t + (RxOhFrameRamInst1_t - RxOhFrameRamInst0_t) * asic_inst) : 
             (TxOhFrameRamInst0_t + (TxOhFrameRamInst1_t - TxOhFrameRamInst0_t) * asic_inst);

    for (i = 0; i < 6; i++) 
    {
        entry = i + frame_id * SYS_FLEXE_OHRAM_BLKNUM;
        index = DRV_INS(flexe_shim_id, entry);
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &oh_ram));
        DRV_IOR_FIELD(lchip, tbl_id, RxOhFrameRamInst0_ohFrame_f, &val32_raw, &oh_ram);
        for (oh_field = 0; oh_field < FLEXE_OH_FIELD_MAX; oh_field++) 
        {
            if (i != g_flexe_oh_field_info[oh_field][FLEXE_OH_INFO_HALF_BLK_ID])
            {
                continue;
            }
            mask = ~(g_flexe_oh_field_info[oh_field][FLEXE_OH_INFO_MASK]);
            start_bit = g_flexe_oh_field_info[oh_field][FLEXE_OH_INFO_START_BIT];
            p_val[oh_field] = (val32_raw & mask) >> start_bit;
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_readout_ohmf(uint8 lchip, sys_flexe_group_t* group_node, uint8 asic_inst, sys_flexe_oh_field_t oh_field)
{
    uint8  i                        = 0;
    uint8  diff                     = 0;
    uint8  speed_mode               = 0;
    uint32 frame_id                 = 0;
    uint32 read_frame_cnt           = 0;
    uint32 frame_num                = 0;
    uint32 crac_mf[SYS_FLEXE_OH_FRAME_NUM] = {0};

     _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);
    if (CTC_PORT_SPEED_50G != speed_mode)
    {
        frame_num = SYS_FLEXE_OH_FRAME_NUM;
    }
    else
    {
        frame_num = SYS_FLEXE_OH_FRAME_NUM_50G;
    }

    while (1)
    {
        /* read C0 from ohram */
        _sys_tmm_flexe_read_ohram_per_fld(lchip, group_node->flexe_shim_id, frame_id, asic_inst, oh_field, &crac_mf[frame_id], SYS_FLEXE_DIR_RX);

        /* frame_id is in [0, frame_num) */
        frame_id++;
        if (frame_id >= frame_num)
        {
            frame_id = frame_id % frame_num;
        }

        /* when read enough frames, check C0 is all the same */
        read_frame_cnt++;
        if (read_frame_cnt >= frame_num) 
        {
            diff = 0;
            for (i = 1; i < frame_num; i++)
            {
                if (crac_mf[i] != crac_mf[0])
                {
                    diff++;
                }
            }
            /* if same, stop read */
            if (0 == diff)
            {
                break;
            }
        }

        /* report error after 50 round*/
        if ((read_frame_cnt / frame_num) >= 50)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] read flexe shim id %d instance id %d rx ohram over time!\n", group_node->flexe_shim_id, asic_inst);
            return CTC_E_INVALID_PARAM;
        }

        /* sleep 1ms after a round*/
        if (0 == (read_frame_cnt % frame_num))
        {
            sal_task_sleep(1);
        }
    }
    
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_parse_ohram(uint8 lchip, 
                           sys_flexe_group_t* group_node, 
                           uint8 asic_inst, 
                           sys_flexe_ohram_info_t* p_ohram_info, 
                           sys_flexe_dir_t dir)
{
    uint32 frame_id                 = 0;
    uint32 frame_num                = 0;
    uint32 slot_num                 = 0;
    /*control of which FlexE instances are members of this group*/
    uint32 flexe_map[CTC_FLEXE_OH_MF_NUM] = {0};
    /*client carried calendar A/B slot 0~9 or 0~19*/
    uint8  i                        = 0;
    uint8  j                        = 0;
    uint8  speed_mode               = 0;
    uint8  ohlock                   = 0;
    uint8  ohmflock                 = 0;
    uint32 **inst_client_map = NULL;
    uint32 **inst_client_map_b = NULL;
    uint32 ohram_info[FLEXE_OH_FIELD_MAX] = {0};
    int32  ret = CTC_E_NONE;

    FLEXE_DBG_PRINTF("FlexE group %d inst %d parse ohram, dir %d!\n", group_node->group_id, asic_inst, dir);

    if (SYS_FLEXE_UNUSED_FLAG_U8 == group_node->flexe_shim_id)
    {
        return CTC_E_INVALID_PARAM;
    }

    CTC_ERROR_RETURN(_sys_tmm_flexe_get_inst_ohlock(lchip, group_node->flexe_shim_id, asic_inst, &ohlock));
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_inst_ohmflock(lchip, group_node->flexe_shim_id, asic_inst, &ohmflock));
    if (!ohlock || !ohmflock)
    {
        return CTC_E_NOT_READY;
    }

    /* Step #1, garantee all multi-frame all updated! */
    if (SYS_FLEXE_DIR_RX == dir)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_readout_ohmf(lchip, group_node, asic_inst, FLEXE_OH_FIELD_CR));
    }

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);
    if (CTC_PORT_SPEED_50G != speed_mode)
    {
        frame_num = SYS_FLEXE_OH_FRAME_NUM;
        slot_num = SYS_FLEXE_OH_MAX_SLOT_PER_INST;
    }
    else
    {
        frame_num = SYS_FLEXE_OH_FRAME_NUM_50G;
        slot_num = MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST);
    }

    inst_client_map = (uint32**)mem_malloc(MEM_DMPS_MODULE, sizeof(uint32*)*MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT));
    if (!inst_client_map)
    {
        return CTC_E_NO_MEMORY;
    }
    inst_client_map_b = (uint32**)mem_malloc(MEM_DMPS_MODULE, sizeof(uint32*)*MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT));
    if (!inst_client_map_b)
    {
        mem_free(inst_client_map);
        return CTC_E_NO_MEMORY;
    }

    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        inst_client_map[i] = (uint32*)mem_malloc(MEM_DMPS_MODULE, sizeof(uint32)*SYS_FLEXE_OH_MAX_SLOT_PER_INST);
        if (!inst_client_map[i])
        {
            ret = CTC_E_NO_MEMORY;
            goto RELEASE_PTR_RETURN;
        }
        sal_memset(inst_client_map[i], 0, sizeof(uint32)*SYS_FLEXE_OH_MAX_SLOT_PER_INST);
        inst_client_map_b[i] = (uint32*)mem_malloc(MEM_DMPS_MODULE, sizeof(uint32)*SYS_FLEXE_OH_MAX_SLOT_PER_INST);
        if (!inst_client_map_b[i])
        {
            ret = CTC_E_NO_MEMORY;
            goto RELEASE_PTR_RETURN;
        }
        sal_memset(inst_client_map_b[i], 0, sizeof(uint32)*SYS_FLEXE_OH_MAX_SLOT_PER_INST);
    }

    /* Step #2, read different ohram fields in different frames! */
    for(frame_id = 0; frame_id < frame_num; frame_id++)
    {
        CTC_ERROR_GOTO(_sys_tmm_flexe_read_ohram(lchip, group_node->flexe_shim_id, frame_id, asic_inst, ohram_info, dir), ret, RELEASE_PTR_RETURN);

        flexe_map[frame_id]  = ohram_info[FLEXE_OH_FIELD_MAP];
        FLEXE_DBG_PRINTF("\nDP %d, flexe_map[%d] = 0x%02x\n", group_node->flexe_shim_id, frame_id, flexe_map[frame_id]);
        if (frame_id < slot_num)
        {
            inst_client_map[asic_inst][frame_id] = ohram_info[FLEXE_OH_FIELD_CAL_A];
            FLEXE_DBG_PRINTF("inst_client_map[%d][%d] = %d\n", asic_inst, frame_id, inst_client_map[asic_inst][frame_id]);
            inst_client_map_b[asic_inst][frame_id] = ohram_info[FLEXE_OH_FIELD_CAL_B] | ( ohram_info[FLEXE_OH_FIELD_CAL_B_15] << 15);
            FLEXE_DBG_PRINTF("inst_client_map_b[%d][%d] = %d\n", asic_inst, frame_id, inst_client_map_b[asic_inst][frame_id]);
        }
    }

    FLEXE_DBG_PRINTF("{ %s @ %d } cr %u\n", __FUNCTION__, __LINE__, ohram_info[FLEXE_OH_FIELD_CR]);
    FLEXE_DBG_PRINTF("{ %s @ %d } ca %u\n", __FUNCTION__, __LINE__, ohram_info[FLEXE_OH_FIELD_CA]);
    FLEXE_DBG_PRINTF("{ %s @ %d } c0 %u\n", __FUNCTION__, __LINE__, ohram_info[FLEXE_OH_FIELD_C_0]);
    FLEXE_DBG_PRINTF("{ %s @ %d } c1 %u\n", __FUNCTION__, __LINE__, ohram_info[FLEXE_OH_FIELD_C_1]);
    FLEXE_DBG_PRINTF("{ %s @ %d } c2 %u\n", __FUNCTION__, __LINE__, ohram_info[FLEXE_OH_FIELD_C_2]);
    FLEXE_DBG_PRINTF("{ %s @ %d } sc %u\n", __FUNCTION__, __LINE__, ohram_info[FLEXE_OH_FIELD_SC]);
    FLEXE_DBG_PRINTF("{ %s @ %d } group_num %u\n", __FUNCTION__, __LINE__, ohram_info[FLEXE_OH_FIELD_GRP_NUM]);
    FLEXE_DBG_PRINTF("{ %s @ %d } inst_num %u\n", __FUNCTION__, __LINE__, ohram_info[FLEXE_OH_FIELD_INST_NUM]);
    p_ohram_info->cr        = ohram_info[FLEXE_OH_FIELD_CR];
    p_ohram_info->ca        = ohram_info[FLEXE_OH_FIELD_CA];
    p_ohram_info->c0        = ohram_info[FLEXE_OH_FIELD_C_0];
    p_ohram_info->c1        = ohram_info[FLEXE_OH_FIELD_C_1];
    p_ohram_info->c2        = ohram_info[FLEXE_OH_FIELD_C_2];
    p_ohram_info->rpf       = ohram_info[FLEXE_OH_FIELD_RPF];
    p_ohram_info->sc        = ohram_info[FLEXE_OH_FIELD_SC];
    p_ohram_info->group_num = ohram_info[FLEXE_OH_FIELD_GRP_NUM];
    p_ohram_info->inst_num  = ohram_info[FLEXE_OH_FIELD_INST_NUM];

    sal_memcpy(p_ohram_info->flexe_map, flexe_map, CTC_FLEXE_OH_MF_NUM * sizeof(uint32));
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        for (j = 0; j < SYS_FLEXE_OH_MAX_SLOT_PER_INST; j++)
        {
            p_ohram_info->inst_client_map[i][j] = inst_client_map[i][j];
            p_ohram_info->inst_client_map_b[i][j] = inst_client_map_b[i][j];
        }
    }

    for(frame_id = 0; frame_id < frame_num; frame_id++)
    {
        if (frame_id < slot_num)
        {
            FLEXE_DBG_PRINTF("p_ohram_info->inst_client_map[%d][%d] = %d\n", asic_inst, frame_id, p_ohram_info->inst_client_map[asic_inst][frame_id]);
            FLEXE_DBG_PRINTF("p_ohram_info->inst_client_map_b[%d][%d] = %d\n", asic_inst, frame_id, p_ohram_info->inst_client_map_b[asic_inst][frame_id]);
        }
    }

RELEASE_PTR_RETURN:
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        if (inst_client_map[i])
        {
            mem_free(inst_client_map[i]);
        }
        if (inst_client_map_b[i])
        {
            mem_free(inst_client_map_b[i]);
        }
    }
    if (inst_client_map)
    {
        mem_free(inst_client_map);
    }
    if (inst_client_map_b)
    {
        mem_free(inst_client_map_b);
    }
    return ret;
}

STATIC int32
_sys_tmm_flexe_mac_prop_clear(uint8 lchip, uint16 lport, uint16 mac_id)
{
    /* set mac rx pkt disable */
    CTC_ERROR_RETURN(_sys_tmm_mac_set_mac_rx_en(lchip, mac_id, 0));
    /* clear unidir cfg */
    CTC_ERROR_RETURN(_sys_tmm_mac_set_unidir_en(lchip, lport, FALSE, TRUE));
    /* recover ipg to default value */
    CTC_ERROR_RETURN(_sys_tmm_mac_set_ipg(lchip, lport, 12));
    /* recover preamble cfg to default value */
    CTC_ERROR_RETURN(_sys_tmm_mac_set_internal_property(lchip, lport, CTC_PORT_PROP_PREAMBLE, 8));
    /* recover padding cfg to default value */
    CTC_ERROR_RETURN(_sys_tmm_mac_set_internal_property(lchip, lport, CTC_PORT_PROP_PADING_EN, 1));

    CTC_ERROR_RETURN(_sys_tmm_mac_set_internal_property(lchip, lport, CTC_PORT_PROP_CHK_CRC_EN, 1));
    CTC_ERROR_RETURN(_sys_tmm_mac_set_internal_property(lchip, lport, CTC_PORT_PROP_STRIP_CRC_EN, 1));
    CTC_ERROR_RETURN(_sys_tmm_mac_set_internal_property(lchip, lport, CTC_PORT_PROP_APPEND_CRC_EN, 1));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_enable(uint8 lchip, uint8 cs_id, uint8 *p_en)
{
    uint8 txqm_id = 0;

    SYS_TMM_FLEXE_CS_2_TXQM(cs_id, txqm_id);
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_hw_enable(lchip, txqm_id, p_en));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_idle_chanid(uint8 lchip, uint8 arrange_type, uint8 dp_id, uint8* p_chan_id, uint8* flexe_supp)
{
    uint8  find_flag = FALSE;
    uint8  tmp_arrange_type;
    uint8  chan_id;
    uint8  dp_chan_id;
    sys_resource_manage_item_info_t *p_channel_arrange = p_usw_datapath_master[lchip]->resource_manage.channel_arrange;

    for(dp_chan_id = 0; dp_chan_id < SYS_TMM_CHANNEL_NUM_PER_DP; dp_chan_id++)
    {
        chan_id = dp_chan_id + dp_id*SYS_TMM_CHANNEL_NUM_PER_DP;
        tmp_arrange_type = p_channel_arrange[chan_id].arrange_type;

        SYS_CONDITION_CONTINUE(!SYS_BMP_IS_SET(tmp_arrange_type, SYS_BMP_TO_VAL_U8(arrange_type)));

        SYS_USW_VALID_PTR_WRITE(flexe_supp, 1);

        if (NULL == p_chan_id)
        {
            continue;
        }

        if(SYS_RESOURCE_BUTT == p_channel_arrange[chan_id].using_stat)
        {
            find_flag = TRUE;
            break;
        }
    }
    if(!find_flag && p_chan_id)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% Cannot get available channel! arrange_type %u, dp_id %u\n", 
            arrange_type, dp_id);
        return CTC_E_NO_RESOURCE;
    }

    SYS_USW_VALID_PTR_WRITE(p_chan_id, chan_id);

    return CTC_E_NONE;
}

int32
_sys_tmm_flexe_restore_eth_mac_configure(uint8 lchip, sys_tmm_ds_target_attr_t *p_ds_attr)
{
    uint8 lport_idx                  = 0;
    uint16 tmp_lport                 = 0;
    uint32 port_fec_val              = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;

    for(lport_idx = 0; lport_idx < p_ds_attr->lport_num; lport_idx++)
    {
        tmp_lport = p_ds_attr->lport_list[lport_idx].lport;
        SYS_CONDITION_CONTINUE(SYS_USW_MAX_PORT_NUM_PER_CHIP <= tmp_lport);

        port_fec_val = p_usw_mac_master[lchip]->mac_prop[tmp_lport].port_fec_val;

        CTC_ERROR_RETURN(sys_tmm_datapath_get_port_attr(lchip, tmp_lport, &port_attr));

        if ((SYS_DMPS_NETWORK_PORT == port_attr->port_type))
        {
            CTC_ERROR_RETURN(_sys_tmm_mac_set_mac_config(lchip, tmp_lport, port_attr->pcs_mode, port_fec_val, port_attr->port_type, FALSE));
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_enable(uint8 lchip, uint8 cs_id)
{
    uint8 i = 0;
    uint8 en = 0;
    uint8 adj_cs_id = (cs_id % 2) ? (cs_id-1) : (cs_id+1);
    uint8 base_logical_serdes = 0;
    uint8 txqm_id = 0;
    uint8 flexe_shim_id = 0;
    uint8 flexe_supp = 0;
    uint8 serdes_lport_cnt = 0;
    uint8 serdes_chan[TMM_MAX_SERDES_NUM_PER_CS] = {0};
    uint16 serdes_lport[TMM_MAX_SERDES_NUM_PER_CS] = {0};
    sys_tmm_ds_target_attr_t    ds_attr;
    sys_datapath_serdes_info_t* p_serdes = NULL;
    sys_datapath_lport_attr_t*  port_attr = NULL;
    sys_resource_manage_item_info_t *p_macid_arrange   = p_usw_datapath_master[lchip]->resource_manage.macid_arrange;

    /* 1. check enable already */
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_enable(lchip, cs_id, &en));
    if (en)
    {
        return CTC_E_NONE;
    }

    /* 2. check Network channel resource */
    SYS_TMM_FLEXE_CS_2_SHIM(cs_id, flexe_shim_id);
    _sys_tmm_flexe_get_idle_chanid(lchip, SYS_ARRANGE_FLEXE_PORT_BMP, flexe_shim_id, NULL, &flexe_supp);
    if (0 == flexe_supp)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] DP %d not support FlexE \n", flexe_shim_id);
        return CTC_E_NOT_SUPPORT;
    }

    SYS_FLEXE_CS_2_BASE_LOGIC_SERDES(cs_id, base_logical_serdes);
    sal_memset(&ds_attr, 0, sizeof(sys_tmm_ds_target_attr_t));

    /* 3. disable ethernet */
    for (i = 0; i < TMM_MAX_SERDES_NUM_PER_CS; i++)
    {
        CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, (base_logical_serdes+i), &p_serdes));
        p_serdes->flexe_flag = 1;
        SYS_CONDITION_CONTINUE(SYS_COMMON_USELESS_MAC == p_serdes->lport);

        CTC_ERROR_RETURN(sys_tmm_datapath_get_port_attr(lchip, p_serdes->lport, &port_attr));
        SYS_CONDITION_CONTINUE(!port_attr || (SYS_TMM_USELESS_ID16 == port_attr->mac_id));

        /* 3.1 clear mac enable cfg */
        CTC_ERROR_RETURN(_sys_tmm_mac_set_mac_en(lchip, p_serdes->lport, FALSE));
        /* 3.2 clear mac property cfg */
        CTC_ERROR_RETURN(_sys_tmm_flexe_mac_prop_clear(lchip, p_serdes->lport, port_attr->mac_id));

        serdes_lport[i] = p_serdes->lport;
        serdes_chan[i] = port_attr->chan_id;

        /* 3.3 queue flush */
        CTC_ERROR_RETURN(sys_usw_add_port_to_channel(lchip, p_serdes->lport, MCHIP_CAP(SYS_CAP_CHANID_DROP), 0));

        /* 3.4 soft table rebuild */
        port_attr->mac_id_reserve = port_attr->mac_id;
        port_attr->flexe_en = 1;
    }
    SYS_TMM_FLEXE_CS_2_TXQM(cs_id, txqm_id);
    for (i = 0; i < SYS_TMM_MAX_MAC_NUM_PER_TXQM; i++)
    {
        p_macid_arrange[SYS_TMM_MAX_MAC_NUM_PER_TXQM*txqm_id+i].using_stat = SYS_RESOURCE_FREE;
    }

    /* 3.5 clear datapath cfg */
    for (i = 0; i < TMM_MAX_SERDES_NUM_PER_CS; i++)
    {
        ds_attr.serdes_list[i].logic_serdes_id = (base_logical_serdes+i);
        SYS_CONDITION_CONTINUE((i < (TMM_MAX_SERDES_NUM_PER_CS-1)) && (serdes_lport[i] == serdes_lport[i+1]));

        ds_attr.lport_num = serdes_lport_cnt+1;
        ds_attr.lport_list[serdes_lport_cnt].lport = serdes_lport[i];
        ds_attr.lport_list[serdes_lport_cnt].chan_id = serdes_chan[i];
        ds_attr.lport_list[serdes_lport_cnt].upt_flag = SYS_DS_LPORT_REMAIN;
        ds_attr.lport_list[serdes_lport_cnt].serdes_relate_num = 0;
        serdes_lport_cnt++;
    }
    ds_attr.serdes_num = TMM_MAX_SERDES_NUM_PER_CS;
    CTC_ERROR_RETURN(_sys_tmm_dynamic_switch_datapath(lchip, &ds_attr));

    /* 3.6 update port type */
    for (i = 0; i < TMM_MAX_SERDES_NUM_PER_CS; i++)
    {
        CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, (base_logical_serdes+i), &p_serdes));
        SYS_CONDITION_CONTINUE(SYS_COMMON_USELESS_MAC == p_serdes->lport);
        CTC_ERROR_RETURN(sys_tmm_datapath_get_port_attr(lchip, p_serdes->lport, &port_attr));
        SYS_CONDITION_CONTINUE(!port_attr);
        port_attr->port_type = SYS_DMPS_INACTIVE_NETWORK_PORT;
    }
    for (i = 0; i < TMM_MAX_SERDES_NUM_PER_CS; i++)
    {
        CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, (base_logical_serdes+i), &p_serdes));
        SYS_CONDITION_CONTINUE(SYS_COMMON_USELESS_MAC == p_serdes->lport);
        CTC_ERROR_RETURN(sys_tmm_datapath_get_port_attr(lchip, p_serdes->lport, &port_attr));
        SYS_CONDITION_CONTINUE(!port_attr);
        port_attr->mac_id = SYS_TMM_USELESS_ID16;
    }

    /* 4. enable FlexE */
    /* 4.1 check if FlexE shim already enable */
    _sys_tmm_flexe_get_enable(lchip, adj_cs_id, &en);
    if (!en)  /* current CS is disable, adjacent is disable, then enable FlexE shim */
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_en_cfg(lchip, cs_id/2, TRUE));
    }
    else
    {
        /* Debug only */
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] RlmCs %d trigger FlexE enable, but FlexE shim %d already enable, won't config FlexE registers. \n", cs_id, cs_id/2);
    }
    /* 4.2 */
    CTC_ERROR_RETURN(_sys_tmm_flexe_macpcs_en_cfg(lchip, cs_id/2, cs_id, TRUE));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_disable(uint8 lchip, uint8 cs_id)
{
    uint8 i = 0;
    uint8 en = 0;
    uint8 adj_cs_id = (cs_id % 2) ? (cs_id-1) : (cs_id+1);
    uint8 cs_used = 0;
    uint8 base_logical_serdes = 0;
    uint16 serdes_lport[TMM_MAX_SERDES_NUM_PER_CS] = {0};
    uint8 serdes_chan[TMM_MAX_SERDES_NUM_PER_CS] = {0};
    uint8 serdes_lport_cnt = 0;
    sys_datapath_serdes_info_t* p_serdes = NULL;
    sys_datapath_lport_attr_t*  port_attr = NULL;
    sys_tmm_ds_target_attr_t    ds_attr;
    sys_resource_manage_item_info_t *p_macid_arrange   = p_usw_datapath_master[lchip]->resource_manage.macid_arrange;

    /* 1. check disable already */
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_enable(lchip, cs_id, &en));
    if (!en)
    {
        return CTC_E_NONE;
    }
    /* 2. check whether the cs which serdes belong has groups */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_flexe_cs_used(lchip, cs_id, &cs_used));
    if (cs_used)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] CS %d is busy, CANNOT disable FlexE!\n", cs_id);
        return CTC_E_INVALID_PARAM;
    }

    /* 3. disable FlexE */
    /* 3.1 check if FlexE shim already disable */

    _sys_tmm_flexe_get_enable(lchip, adj_cs_id, &en);
    if (!en) /* current CS is enable, adjacent is disable, then disable FlexE shim */
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_en_cfg(lchip, cs_id/2, FALSE));
    }
    else
    {
        /* Debug only */
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] RlmCs %d trigger FlexE disable, but FlexE shim %d still in use by other CS, won't config FlexE registers. \n", cs_id, cs_id/2);
    }

    /* 4. resume ethernet */
    SYS_FLEXE_CS_2_BASE_LOGIC_SERDES(cs_id, base_logical_serdes);
    sal_memset(&ds_attr, 0, sizeof(sys_tmm_ds_target_attr_t));

    /* 4.1 mac disable */
    for (i = 0; i < TMM_MAX_SERDES_NUM_PER_CS; i++)
    {
        CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, (base_logical_serdes+i), &p_serdes));
        p_serdes->flexe_flag = 0;
        SYS_CONDITION_CONTINUE(SYS_COMMON_USELESS_MAC == p_serdes->lport);
        CTC_ERROR_RETURN(sys_tmm_datapath_get_port_attr(lchip, p_serdes->lport, &port_attr));
        SYS_CONDITION_CONTINUE(!port_attr);
        port_attr->mac_id = port_attr->mac_id_reserve;
        SYS_CONDITION_CONTINUE(320 <= port_attr->mac_id);
        p_macid_arrange[port_attr->mac_id].using_stat = SYS_RESOURCE_IN_USE;

        serdes_lport[i] = p_serdes->lport;
        serdes_chan[i] = port_attr->chan_id;
        /* 3.2 other clear */

        /* 3.3 queue flush */

        /* 3.4 soft table rebuild */
        port_attr->flexe_en  = 0;
        port_attr->port_type = SYS_DMPS_NETWORK_PORT;
    }

    for (i = 0; i < TMM_MAX_SERDES_NUM_PER_CS; i++)
    {
        ds_attr.serdes_list[i].logic_serdes_id = (base_logical_serdes+i);
        SYS_CONDITION_CONTINUE((i < (TMM_MAX_SERDES_NUM_PER_CS-1)) && (serdes_lport[i] == serdes_lport[i+1]));

        ds_attr.lport_num = serdes_lport_cnt+1;
        ds_attr.lport_list[serdes_lport_cnt].lport = serdes_lport[i];
        ds_attr.lport_list[serdes_lport_cnt].chan_id = serdes_chan[i];
        ds_attr.lport_list[serdes_lport_cnt].upt_flag = SYS_DS_LPORT_REMAIN;
        ds_attr.lport_list[serdes_lport_cnt].serdes_relate_num = 0;
        serdes_lport_cnt++;
    }
    ds_attr.serdes_num = 8;

    /* 3.5 datapath update */
    CTC_ERROR_RETURN(_sys_tmm_dynamic_switch_datapath(lchip, &ds_attr));
    /* add port to channel */
    for (i = 0; i < TMM_MAX_SERDES_NUM_PER_CS; i++)
    {
        CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, (base_logical_serdes+i), &p_serdes));
        SYS_CONDITION_CONTINUE(SYS_COMMON_USELESS_MAC == p_serdes->lport);
        CTC_ERROR_RETURN(sys_tmm_datapath_get_port_attr(lchip, p_serdes->lport, &port_attr));
        SYS_CONDITION_CONTINUE(!port_attr || (SYS_TMM_USELESS_ID16 == port_attr->mac_id));
        CTC_ERROR_RETURN(sys_usw_add_port_to_channel(lchip, p_serdes->lport, port_attr->chan_id, 0));
    }

    CTC_ERROR_RETURN(_sys_tmm_flexe_macpcs_en_cfg(lchip, cs_id/2, cs_id, FALSE));
    CTC_ERROR_RETURN(_sys_tmm_flexe_restore_eth_mac_configure(lchip, &ds_attr));

    return CTC_E_NONE;
}

int32
_sys_tmm_flexe_inst_ow_inact_oh(uint8 lchip, uint8 flexe_shim_id, uint8 inst_id, uint8 ohmf_cnt, uint8 oh_field_type, void *p_data)
{
    uint8  i        = 0;
    uint8  frame_id = 0;
    uint8  offset   = 0;
    uint8  tmp_inst_id = 0;
    uint32 tmp_client_number = 0;
    uint32 tmp_inst_number = 0;

    uint32 client_bit_15 = 0;
    uint32 tmp_val32 = 0; 
    int32  ret = CTC_E_NONE;
    sys_flexe_group_t *group_node = NULL;
    uint32 **val_cfg = NULL;

    ret = _sys_tmm_flexe_inst_ow_inact_oh_pc(lchip, flexe_shim_id, inst_id, ohmf_cnt, oh_field_type, p_data);
    if (ret)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] %s @ %d instance %d write overhead param check fail!\n", \
            __FUNCTION__, __LINE__, inst_id);
        return ret;
    }

    val_cfg = (uint32**)mem_malloc(MEM_DMPS_MODULE, sizeof(uint32*)*FLEXE_OH_FIELD_MAX);
    if (!val_cfg)
    {
        return CTC_E_NO_MEMORY;
    }
    for (i = 0; i < FLEXE_OH_FIELD_MAX; i++)
    {
        val_cfg[i] = (uint32*)mem_malloc(MEM_DMPS_MODULE, sizeof(uint32)*SYS_FLEXE_OH_FRAME_NUM);
        if (!val_cfg[i])
        {
            ret = CTC_E_NO_MEMORY;
            goto RELEASE_PTR_RETURN;
        }
        sal_memset(val_cfg[i], 0, sizeof(uint32)*SYS_FLEXE_OH_FRAME_NUM);
    }

    group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, flexe_shim_id, inst_id);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] %s @ %d Asic inst %d not belong to any group!\n", __FUNCTION__, __LINE__, inst_id);
        ret = CTC_E_INVALID_PARAM;
        goto RELEASE_PTR_RETURN;
    }

    /*flexe map*/
    if (FLEXE_OH_FIELD_TYPE_FLEXE_MAP == oh_field_type)
    {
        for(i = 0; i < group_node->inst_cnt; i++)
        {
            tmp_inst_id = group_node->inst_list[i];
            SYS_CONDITION_CONTINUE((SYS_FLEXE_OH_FRAME_NUM_50G != ohmf_cnt) && (tmp_inst_id%2));
            _sys_tmm_flexe_get_inst_number(lchip, flexe_shim_id, tmp_inst_id, &tmp_inst_number);
            SYS_CONDITION_CONTINUE(0 == tmp_inst_number);
            frame_id = tmp_inst_number / 8;
            offset   = tmp_inst_number % 8;
            val_cfg[FLEXE_OH_FIELD_MAP][frame_id] |= (0x01 << offset);
        }
    }
    else
    {
        for (frame_id = 0; frame_id < ohmf_cnt; frame_id++)
        {
            switch (oh_field_type)
            {
            case FLEXE_OH_FIELD_TYPE_GROUP_NUM:
                tmp_val32 = *(uint32 *)p_data;
                val_cfg[FLEXE_OH_FIELD_GRP_NUM][frame_id] = tmp_val32;
                break;
            case FLEXE_OH_FIELD_TYPE_INST_NUM:
                tmp_val32 = *(uint32 *)p_data;
                val_cfg[FLEXE_OH_FIELD_INST_NUM][frame_id] = tmp_val32;
                break;
            case FLEXE_OH_FIELD_TYPE_CLIENT_CAL_A:
                tmp_val32 = *((uint32 *)p_data + frame_id);
                _sys_tmm_flexe_read_ohram_per_fld(lchip, flexe_shim_id, frame_id, inst_id, FLEXE_OH_FIELD_CAL_B,
                    &tmp_client_number, SYS_FLEXE_DIR_TX);
                _sys_tmm_flexe_read_ohram_per_fld(lchip, flexe_shim_id, frame_id, inst_id, FLEXE_OH_FIELD_CAL_B_15,
                    &client_bit_15, SYS_FLEXE_DIR_TX);
                val_cfg[FLEXE_OH_FIELD_CAL_B][frame_id]    = tmp_client_number;
                val_cfg[FLEXE_OH_FIELD_CAL_B_15][frame_id] = client_bit_15;
                val_cfg[FLEXE_OH_FIELD_CAL_A][frame_id]    = tmp_val32;
                break;
            case FLEXE_OH_FIELD_TYPE_CLIENT_CAL_B:
                tmp_val32 = *((uint32 *)p_data + frame_id);
                _sys_tmm_flexe_read_ohram_per_fld(lchip, group_node->flexe_shim_id, frame_id, inst_id, FLEXE_OH_FIELD_CAL_A,
                    &tmp_client_number, SYS_FLEXE_DIR_TX);
                val_cfg[FLEXE_OH_FIELD_CAL_A][frame_id]    = tmp_client_number;
                val_cfg[FLEXE_OH_FIELD_CAL_B][frame_id]    = (0x00007fff & tmp_val32);
                val_cfg[FLEXE_OH_FIELD_CAL_B_15][frame_id] = (0x00000001 & (tmp_val32 >> 15));
                break;
            case FLEXE_OH_FIELD_TYPE_CR:
                tmp_val32 = *(uint32 *)p_data;
                val_cfg[FLEXE_OH_FIELD_CR][frame_id]      = tmp_val32;
                break;
            case FLEXE_OH_FIELD_TYPE_CA:
                tmp_val32 = *(uint32 *)p_data;
                val_cfg[FLEXE_OH_FIELD_CA][frame_id]      = tmp_val32;
                break;
            case FLEXE_OH_FIELD_TYPE_C_BIT:
                tmp_val32 = *(uint32 *)p_data;
                val_cfg[FLEXE_OH_FIELD_C_0][frame_id]     = tmp_val32;
                val_cfg[FLEXE_OH_FIELD_C_1][frame_id]     = tmp_val32;
                val_cfg[FLEXE_OH_FIELD_C_2][frame_id]     = tmp_val32;
                break;
            case FLEXE_OH_FIELD_TYPE_CR_C:
                tmp_val32 = *(uint32 *)p_data;
                val_cfg[FLEXE_OH_FIELD_CR][frame_id]      = tmp_val32;
                val_cfg[FLEXE_OH_FIELD_C_0][frame_id]     = tmp_val32;
                val_cfg[FLEXE_OH_FIELD_C_1][frame_id]     = tmp_val32;
                val_cfg[FLEXE_OH_FIELD_C_2][frame_id]     = tmp_val32;
                break;
            case FLEXE_OH_FIELD_TYPE_SC:
                tmp_val32 = *(uint32 *)p_data;
                val_cfg[FLEXE_OH_FIELD_SC][frame_id]      = tmp_val32;
                break;
            default:
                break;
            }
        }
    }

    CTC_ERROR_GOTO(_sys_tmm_flexe_inst_hw_ow_oh(lchip, flexe_shim_id, inst_id, ohmf_cnt, oh_field_type, val_cfg), ret, RELEASE_PTR_RETURN);

RELEASE_PTR_RETURN:
    for (i = 0; i < FLEXE_OH_FIELD_MAX; i++)
    {
        if (val_cfg[i])
        {
            mem_free(val_cfg[i]);
        }
    }
    if (val_cfg)
    {
        mem_free(val_cfg);
    }

    return ret;
}


STATIC int32
_sys_tmm_flexe_group_ow_inact_oh(uint8 lchip, sys_flexe_group_t* group_node, uint8 oh_field_type, void *p_data)
{
    uint8  i           = 0;
    uint8  j           = 0;
    int8   si          = 0;
    uint8  phy_speed   = 0;
    uint8  inst_id     = 0;
    uint8  ohmf_cnt    = 0;
    uint32 oh_phy_inst_number[SYS_FLEXE_MAX_INST_CNT] = {0};
    uint32 inact_client_cal[SYS_FLEXE_MAX_INST_CNT][SYS_FLEXE_OH_MAX_SLOT_PER_INST] = {{0}};

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    FLEXE_DBG_PRINTF("\n ### %s @ %d, group_id: %d, oh field type: %d\n", __FUNCTION__, __LINE__, group_node->group_id, oh_field_type);

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &phy_speed);
    ohmf_cnt = (CTC_PORT_SPEED_50G == phy_speed) ? SYS_FLEXE_OH_FRAME_NUM_50G : SYS_FLEXE_OH_FRAME_NUM;

    if ((FLEXE_OH_FIELD_TYPE_CLIENT_CAL_A == oh_field_type) || (FLEXE_OH_FIELD_TYPE_CLIENT_CAL_B == oh_field_type))
    {
        for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
        {
            for (j = 0; j < SYS_FLEXE_OH_MAX_SLOT_PER_INST; j++)
            {
                inact_client_cal[i][j] = *((uint32*)p_data + i*SYS_FLEXE_OH_MAX_SLOT_PER_INST + j);
            }
        }
    }

    if (FLEXE_OH_FIELD_TYPE_INST_NUM == oh_field_type)
    {
        for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
        {
            oh_phy_inst_number[i] = *((uint32 *)p_data + i);
        }
    }

    /* from high to low, HW specified */
    for (si = group_node->inst_cnt-1; si >= 0; si--)
    {
        inst_id = group_node->inst_list[si];
        SYS_CONDITION_CONTINUE((CTC_PORT_SPEED_50G != phy_speed) && (inst_id%2));

        if (FLEXE_OH_FIELD_TYPE_SC == oh_field_type)
        {
            /* if 100G/200G/400G PHY, only the lower/even ASIC-inst id need do oh ram config */
            SYS_CONDITION_CONTINUE((CTC_PORT_SPEED_200G == phy_speed) && (inst_id % 4));
            SYS_CONDITION_CONTINUE((CTC_PORT_SPEED_400G == phy_speed) && (0 != inst_id));
        }

        if ((FLEXE_OH_FIELD_TYPE_CLIENT_CAL_A == oh_field_type) || (FLEXE_OH_FIELD_TYPE_CLIENT_CAL_B == oh_field_type))
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_inst_ow_inact_oh(lchip, group_node->flexe_shim_id, inst_id, \
                ohmf_cnt, oh_field_type, (void *)inact_client_cal[inst_id]));
        }
        else if (FLEXE_OH_FIELD_TYPE_INST_NUM == oh_field_type)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_inst_ow_inact_oh(lchip, group_node->flexe_shim_id, inst_id, \
                ohmf_cnt, oh_field_type, (void *)&oh_phy_inst_number[inst_id]));
        }
        else
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_inst_ow_inact_oh(lchip, group_node->flexe_shim_id, inst_id, \
                ohmf_cnt, oh_field_type, p_data));
        }
    }

    return CTC_E_NONE;
}


/* Overwrite instance overhead per group, oh_field_type refers to sys_flexe_oh_field_type_t */
STATIC int32
_sys_tmm_flexe_group_ow_oh(uint8 lchip, sys_flexe_group_t* group_node, uint8 oh_field_type, void *p_data)
{
    uint8 i = 0;
    uint32 inst_mask = 0;
    uint32 oh_bs = 0;

    if (!group_node->inst_cnt)
    {
        return CTC_E_NONE;
    }

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        inst_mask |= 1 << group_node->inst_list[i];
    }

    CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_inact_oh(lchip, group_node, oh_field_type, p_data));
    CTC_ERROR_RETURN(_sys_tmm_flexe_oh_get_banksel_config(lchip, group_node->flexe_shim_id, inst_mask, &oh_bs));
    CTC_ERROR_RETURN(_sys_tmm_flexe_oh_set_banksel_config(lchip, group_node->flexe_shim_id, inst_mask, !oh_bs));
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_inact_oh(lchip, group_node, oh_field_type, p_data));
    CTC_ERROR_RETURN(_sys_tmm_flexe_oh_set_banksel_config(lchip, group_node->flexe_shim_id, inst_mask, oh_bs));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_group_number(uint8 lchip, sys_flexe_group_t *group_node, uint32 val)
{
    uint8 legal = 0;
    _sys_tmm_flexe_check_value_legal(lchip, SYS_FLEXE_CHECK_GROUP_NUM, NULL, (void *)&val, &legal);
    SYS_CONDITION_RETURN(!legal, CTC_E_INVALID_PARAM);

    if (!group_node)
    {
        return CTC_E_NOT_INIT;
    }
    if (val != group_node->group_number)
    {
        group_node->group_number = val;
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_oh(lchip, group_node, FLEXE_OH_FIELD_TYPE_GROUP_NUM, (void *)&val));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_phy_link_intr_mask(uint8 lchip, sys_flexe_group_t *group_node, uint8 mask)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 phy_lane_num = 0;
    uint32 index  = 0;
    uint32 tbl_id = 0;
    uint32 cmd    = 0;
    uint8  cs_id  = 0;
    uint8 pcs_l_id = 0;
    uint32 value[5]    = {0};

    tbl_id = CtcCsCtlInterruptFunc_t;

    _sys_tmm_flexe_get_phy_lane_num(lchip, group_node->phy_list[0].logical_serdes_base, &phy_lane_num);

    for (i = 0; i < group_node->phy_cnt; i++)
    {
        SYS_TMM_GET_RLMCS(group_node->phy_list[i].logical_serdes_base, cs_id);
        for (j = 0; j < phy_lane_num; j++)
        {
            pcs_l_id = group_node->phy_list[i].logical_serdes_base % TMM_MAX_SERDES_NUM_PER_CS + j;
            if (pcs_l_id < 7)  /* 0~6 */
            {
                value[2] |= 0x3 << (17 + 2*pcs_l_id);
            }
            else
            {
                value[2] |= (1 << 31);
                value[3] |= 1;
            }
        }
        if(!mask)
        {
            /*clear link intr*/
            index = DRV_INS(cs_id, 1);
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, value));
            index = DRV_INS(cs_id, 3);
        }
        else
        {
            index = DRV_INS(cs_id, 2);
        }

        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, value));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_phy_static_cfg(uint8 lchip, sys_flexe_group_t* group_node, uint8 is_normal, uint8 enable)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 phy_lane_num = 0;
    uint8 val8 = 0;
    uint8 physical_serdes_id = 0;
    uint32 pcs_link = 0;
    int32 times = 100;

    sys_flexe_client_t *p_client = NULL;
    ctc_slistnode_t* node = NULL;
    sys_datapath_serdes_info_t* p_serdes  = NULL;

    _sys_tmm_flexe_get_phy_lane_num(lchip, group_node->phy_list[0].logical_serdes_base, &phy_lane_num);

    if (enable)
    {
        CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
        {
            p_client = _ctc_container_of(node, sys_flexe_client_t, head);
            if (p_client && (p_client->group_id == group_node->group_id))
            {
                CTC_ERROR_RETURN(_sys_tmm_mcmac_rsv_cfg(lchip, p_client->mac_id, FALSE));
                sal_task_sleep(1);
                CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_writemask(lchip, p_client->flexe_shim_id, p_client->rx_xc_chid, p_client->flow_type, FALSE));
            }
        }
        sal_task_sleep(1);

        for (i = 0; i < group_node->phy_cnt; i++)
        {
            for (j = 0; j < phy_lane_num; j++)
            {
                CTC_ERROR_RETURN(_sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, (group_node->phy_list[i].logical_serdes_base + j), &physical_serdes_id));
                SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == physical_serdes_id), CTC_E_INVALID_PARAM);
                CTC_ERROR_RETURN(sys_tmm_serdes_set_tx_en(lchip, physical_serdes_id, FALSE));
                CTC_ERROR_RETURN(_sys_tmm_datapath_set_internal_loopback_pcs(lchip, physical_serdes_id, enable));
            }
        }
    }
    else
    {
        for (i = 0; i < group_node->phy_cnt; i++)
        {
            for (j = 0; j < phy_lane_num; j++)
            {
                CTC_ERROR_RETURN(_sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, (group_node->phy_list[i].logical_serdes_base + j), &physical_serdes_id));
                SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == physical_serdes_id), CTC_E_INVALID_PARAM);
                CTC_ERROR_RETURN(_sys_tmm_datapath_set_internal_loopback_pcs(lchip, physical_serdes_id, enable));
                if (is_normal)
                {
                    CTC_ERROR_RETURN(sys_tmm_serdes_set_tx_en(lchip, physical_serdes_id, TRUE));
                }
            }
        }

        CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
        {
            p_client = _ctc_container_of(node, sys_flexe_client_t, head);
            if (p_client && (p_client->group_id == group_node->group_id))
            {
                CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_writemask(lchip, p_client->flexe_shim_id, p_client->rx_xc_chid, p_client->flow_type, TRUE));
                sal_task_sleep(1);
                SYS_CONDITION_CONTINUE(SYS_FLEXE_UNUSED_FLAG_U16 == p_client->mac_id);
                CTC_ERROR_RETURN(_sys_tmm_mac_get_flexe_mac_en(lchip, p_client->mac_id, SYS_FLEXE_DIR_TX, &val8));
                if (val8)
                {
                    CTC_ERROR_RETURN(_sys_tmm_mcmac_rsv_cfg(lchip, p_client->mac_id, TRUE));
                }
            }
        }
    }

    if (enable)
    {
        for (i = 0; i < group_node->phy_cnt; i++)
        {
            for (j = 0; j < phy_lane_num; j++)
            {
                CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, (group_node->phy_list[i].logical_serdes_base + j), &p_serdes));
                CTC_ERROR_RETURN(_sys_tmm_mac_get_pcs_link_status(lchip, p_serdes->lport, &pcs_link));
                while (!pcs_link && (times > 0))
                {
                    times--;
                    CTC_ERROR_RETURN(_sys_tmm_mac_get_pcs_link_status(lchip, p_serdes->lport, &pcs_link));
                    sal_task_sleep(1);
                }
            }
        }
    }

    sal_task_sleep(10);

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_hw_cfg(uint8 lchip, sys_flexe_group_t* group_node, uint8 first_bind, uint8 enable)
{
    uint8  i       = 0;
    uint8  inst_id = 0;
    uint32 val32   = 0;

    if (enable)
    {
        /* send rpf value when PHY bind group */
        if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A))
        {    
            for (i = 0; i < group_node->inst_cnt; i++)
            {
                CTC_ERROR_RETURN(_sys_tmm_flexe_set_inst_rpf_val(lchip, group_node->flexe_shim_id, group_node->inst_list[i], TRUE));
            }
        }
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_400g_phy_reset(lchip, group_node));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_phy_config(lchip, group_node, TRUE, first_bind));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_group_en(lchip, group_node, FALSE, first_bind));
        CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_cfg(lchip, group_node, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_group_config(lchip, group_node, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_en(lchip, group_node, TRUE));

        val32 = group_node->group_number;
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_oh(lchip, group_node, FLEXE_OH_FIELD_TYPE_GROUP_NUM, (void*)&val32));
        CTC_ERROR_RETURN(_sys_tmm_flexe_get_cfgrxoh_sync(lchip, group_node, &val32));
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_oh(lchip, group_node, FLEXE_OH_FIELD_TYPE_SC, (void*)&val32));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_group_en(lchip, group_node, TRUE, first_bind));
        if (SYS_FLEXE_STATIC_SWITCH == group_node->switch_mode)
        {
            if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A))
            {
                /* enable switchen */
                CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_en(lchip, group_node, SYS_FLEXE_DIR_TX, TRUE));
                CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_en(lchip, group_node, SYS_FLEXE_DIR_RX, TRUE));
            }
        }
    }
    else
    {
        /* reset rpf value when PHY unbind from group */
        if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A))
        {    
            for (i = 0; i < group_node->inst_cnt; i++)
            {
                CTC_ERROR_RETURN(_sys_tmm_flexe_set_inst_rpf_val(lchip, group_node->flexe_shim_id, group_node->inst_list[i], FALSE));
            }
        }
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_group_en(lchip, group_node, FALSE, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_cfg(lchip, group_node, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_mgr_en(lchip, group_node, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_phy_config(lchip, group_node, FALSE, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_group_config(lchip, group_node, FALSE));
        /* clear ohram */
        for (i = 0; i < group_node->inst_cnt;i++)
        {
            inst_id = group_node->inst_list[i];
            CTC_ERROR_RETURN(_sys_tmm_flexe_oh_get_banksel_config(lchip, group_node->flexe_shim_id, (1<<inst_id), &val32));
            CTC_ERROR_RETURN(_sys_tmm_flexe_oh_set_banksel_config(lchip, group_node->flexe_shim_id, (1<<inst_id), !val32));
            CTC_ERROR_RETURN(_sys_tmm_flexe_ohram_clear_per_inst(lchip, group_node->flexe_shim_id, inst_id));
            CTC_ERROR_RETURN(_sys_tmm_flexe_oh_set_banksel_config(lchip, group_node->flexe_shim_id, (1<<inst_id), val32));
            CTC_ERROR_RETURN(_sys_tmm_flexe_ohram_clear_per_inst(lchip, group_node->flexe_shim_id, inst_id));
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_mem_mgr(uint8 lchip, sys_flexe_group_t* group_node, uint8 phy_cnt, uint8 inst_cnt, uint8 op)
{
    uint8  i              = 0;
    uint8* p_mem          = NULL;
    uint32 mem_size       = 0;
    uint32 phy_list_size  = sizeof(sys_flexe_phy_t)*phy_cnt;
    uint32 inst_list_size = sizeof(uint8)*inst_cnt;
    uint32 dir_inst_size  = sizeof(sys_flexe_dir_inst_t)*MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT);
    uint32 cc_inst_size   = sizeof(sys_flexe_cc_inst_t)*MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT);

    if (op == SYS_TMM_FLEXE_MEM_MGR_OP_MALLOC)
    {
        mem_size += phy_list_size;                                     /* group_node->phy_list */
        mem_size += inst_list_size;                                    /* group_node->inst_list*/
        mem_size += dir_inst_size;                                     /* group_node->tx.dir_inst */
        mem_size += dir_inst_size;                                     /* group_node->rx.dir_inst */
        mem_size += cc_inst_size*2*MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); /* group_node->tx.cc[i].inst group_node->rx.cc[i].inst */

        if (0 == mem_size)
        {
            return CTC_E_NONE;
        }
        p_mem  = (uint8*)mem_malloc(MEM_DMPS_MODULE, mem_size);
        if(NULL == p_mem)
        {
            return CTC_E_NO_MEMORY;
        }
        sal_memset(p_mem, 0, mem_size);

        group_node->phy_list = (sys_flexe_phy_t*)p_mem;
        p_mem += phy_list_size;
        
        group_node->inst_list = (uint8*)p_mem;
        p_mem += inst_list_size;
        
        group_node->tx.dir_inst = (sys_flexe_dir_inst_t*)p_mem;
        p_mem += dir_inst_size;

        group_node->rx.dir_inst = (sys_flexe_dir_inst_t*)p_mem;
        p_mem += dir_inst_size;
        
        for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); i ++)
        {
            group_node->tx.cc[i].inst = (sys_flexe_cc_inst_t*)p_mem;
            p_mem += cc_inst_size;
            
            group_node->rx.cc[i].inst = (sys_flexe_cc_inst_t*)p_mem;
            p_mem += cc_inst_size;
        }
    }
    else
    {
        mem_free(group_node->phy_list);
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_bind_phylist(uint8 lchip, sys_flexe_group_t* group_node, ctc_flexe_phy_t *phylist)
{
    uint8 i = 0, j = 0;
    uint8 flexe_shim_id = 0;
    uint8 logical_serdes_id = 0;
    uint8 first_bind        = FALSE;
    uint8 inst_base         = 0;
    uint8 phy_inst_cnt      = 0;
    uint8 phy_lane_num      = 0;
    uint8 inst_cnt          = 0;
    sys_datapath_serdes_info_t* p_serdes = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, group %d bind phylist\n", __FUNCTION__, __LINE__, group_node->group_id);

    /* param check */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_bind_phylist_pc(lchip, group_node, phylist));
    flexe_shim_id = SYS_TMM_FLEXE_GET_FLEXE_SHIM(phylist->serdes_id[0]);
    first_bind = _sys_tmm_flexe_is_bind_first_phy(lchip, flexe_shim_id);

    FLEXE_DUMP("\n\n\n*************************************************************************\n");
    FLEXE_DUMP("flexe group %d property phy-list ", group_node->group_id);
    for (i = 0; i < phylist->serdes_cnt; i++)
    {
        FLEXE_DUMP(" %d", phylist->serdes_id[i]);
    }
    FLEXE_DUMP("\n");
    FLEXE_DUMP("\n*************************************************************************\n\n");

    _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)phylist->serdes_id[0], &logical_serdes_id);
    SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
    CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, logical_serdes_id, &p_serdes));
    if ((CTC_CHIP_SERDES_LG_MODE == p_serdes->mode) || (CTC_CHIP_SERDES_LG_R1_MODE == p_serdes->mode))
    {
        phy_inst_cnt = 1;
    }
    else if ((CTC_CHIP_SERDES_CG_MODE == p_serdes->mode) || (CTC_CHIP_SERDES_CG_R2_MODE == p_serdes->mode))
    {
        phy_inst_cnt = 2;
    }
    else if (CTC_CHIP_SERDES_CCG_R4_MODE == p_serdes->mode)
    {
        phy_inst_cnt = 4;
    }
    else if (CTC_CHIP_SERDES_CDG_R8_MODE == p_serdes->mode)
    {
        phy_inst_cnt = 8;
    }
    else
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] SerDes ID %d not support FlexE \n", phylist->serdes_id[0]);
        return CTC_E_INVALID_PARAM;
    }

    group_node->flexe_shim_id = flexe_shim_id;
    group_node->phy_cnt       = phylist->serdes_cnt;
    group_node->inst_cnt      = phy_inst_cnt*phylist->serdes_cnt;

    CTC_ERROR_RETURN(_sys_tmm_flexe_group_mem_mgr(lchip, group_node, group_node->phy_cnt, group_node->inst_cnt, SYS_TMM_FLEXE_MEM_MGR_OP_MALLOC));

    _sys_tmm_flexe_init_group_phy_ds(lchip, group_node, FALSE);


    for (i = 0; i < phylist->serdes_cnt; i++)
    {
        _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)phylist->serdes_id[i], &logical_serdes_id);
        SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
        CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, logical_serdes_id, &p_serdes));

        /* alloc instance(s) for each phy */
        CTC_ERROR_RETURN(_sys_tmm_flexe_get_free_instlist(lchip, flexe_shim_id, phy_inst_cnt, &inst_base));
        if (SYS_FLEXE_UNUSED_FLAG_U8 == inst_base)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Cannot get enough free instance for PHY(SerDes) %d!\n",\
                phylist->serdes_id[i]);
            _sys_tmm_flexe_init_group_ds(lchip, group_node);
            return CTC_E_INVALID_PARAM;
        }
        /* set phy-inst mapping */
        group_node->phy_list[i].inst_base = inst_base;
        for (j = 0; j < phy_inst_cnt; j++)
        {
            group_node->inst_list[inst_cnt++] = inst_base+j;
        }

        /* fill phy list ds */
        group_node->phy_list[i].pcs_mode = p_serdes->mode;
        group_node->phy_list[i].fec_type = p_serdes->fec_type;
        SYS_FLEXE_MODE_2_LANE_NUM(p_serdes->mode, phy_lane_num);
        SYS_CONDITION_RETURN(!phy_lane_num, CTC_E_INVALID_PARAM);        
        group_node->phy_list[i].logical_serdes_base = logical_serdes_id / phy_lane_num * phy_lane_num;
    }

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_FLEXE, SYS_WB_APPID_FLEXE_SUBID_GROUP, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_FLEXE, SYS_WB_APPID_FLEXE_SUBID_GROUP_MEM, 1);

    CTC_ERROR_RETURN(_sys_tmm_flexe_group_hw_cfg(lchip, group_node, first_bind, TRUE));

    /* clear abnormal intr, then check 2 times */
    (void)_ctc_tmm_dkit_check_abnormal_intr(lchip, 1);
    (void)_ctc_tmm_dkit_check_abnormal_intr(lchip, 0);
    (void)_ctc_tmm_dkit_check_abnormal_intr(lchip, 0);

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_group_phy_number(uint8 lchip, sys_flexe_group_t* group_node, uint8 logical_serdes_base, uint32 phy_number)
{
    uint8  i                   = 0;
    uint8  phy_speed           = 0;
    uint8  oh_inst_step        = 0;
    uint8  oh_inst_cnt         = 0;
    uint32 shft                = 0;
    uint8  asic_inst           = 0;
    uint32 oh_phy_inst_number[SYS_FLEXE_MAX_INST_CNT] = {0};  /* absolute asic_inst in one FlexE_shim_id.
                                                           if PHY is 100G/200G/400G, only use even index
                                                         */
    sys_flexe_phy_t* p_phy = NULL;

    for (i = 0; i < group_node->phy_cnt;i++)
    {
        if (logical_serdes_base == group_node->phy_list[i].logical_serdes_base)
        {
            p_phy = &group_node->phy_list[i];
            break;
        }
    }
    if (!p_phy)
    {
        return CTC_E_NONE;
    }

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &phy_speed);
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        asic_inst = group_node->inst_list[i];
        SYS_CONDITION_CONTINUE((CTC_PORT_SPEED_50G != phy_speed) && (asic_inst%2));
        _sys_tmm_flexe_get_inst_number(lchip, group_node->flexe_shim_id, asic_inst, &oh_phy_inst_number[asic_inst]);
    }
    oh_inst_step = (CTC_PORT_SPEED_50G == phy_speed) ? 1 : 2;
    oh_inst_cnt  = (CTC_PORT_SPEED_400G == phy_speed) ? 4 : ((CTC_PORT_SPEED_200G == phy_speed) ? 2 : 1);
    shft         = (CTC_PORT_SPEED_400G == phy_speed) ? 2 : ((CTC_PORT_SPEED_200G == phy_speed) ? 1 : 0);

    for (i = 0; i < oh_inst_cnt; i++)
    {
        asic_inst = p_phy->inst_base;
        asic_inst += i*oh_inst_step;
        oh_phy_inst_number[asic_inst] = (phy_number << shft) | i;
    }

    CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_oh(lchip, group_node, FLEXE_OH_FIELD_TYPE_INST_NUM, (void *)oh_phy_inst_number));
    p_phy->phy_number = phy_number;
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_oh(lchip, group_node, FLEXE_OH_FIELD_TYPE_FLEXE_MAP, NULL));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_manual_reset_ohram(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint8 ohlock = 0;
    uint32 crcac = 0;

    /************************* group PHY loopback ************************/
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_phy_link_intr_mask(lchip, group_node, TRUE));
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_phy_static_cfg(lchip, group_node, FALSE, TRUE));

    /* check whether phy in the group is all ohlock */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_ohlock(lchip, group_node, &ohlock));
    if (FALSE == ohlock)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] phy in group %d is not all ohlock, CANNOT run static switch!\n", group_node->group_id);
        return CTC_E_INVALID_PARAM;
    }

    /************************* TX START ************************/
    /* modify cr/ca/c in ohram */
    FLEXE_DBG_PRINTF("\n[FlexE-Debug] group %d Send CR && CA && C value %d\n", group_node->group_id, crcac);
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_oh(lchip, group_node, FLEXE_OH_FIELD_TYPE_CR, (void *)&crcac));
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_send_ca(lchip, group_node, crcac));
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_oh(lchip, group_node, FLEXE_OH_FIELD_TYPE_C_BIT, (void *)&crcac));
    /* disable switch_en */
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_en(lchip, group_node, SYS_FLEXE_DIR_TX, FALSE));
    /* modify switch_sel A */
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_ACTIVE_A));
    /* wait until switch ok */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_ACTIVE_A));
    /* update group tx flag */
    group_node->tx.active = SYS_FLEXE_ACTIVE_A;
    /************************* TX END **************************/

    /************************* RX START ************************/
    /* enable rx_spare */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_set_rx_spare(lchip, group_node, TRUE));
    /* disable switch_en */
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_en(lchip, group_node, SYS_FLEXE_DIR_RX, FALSE));
    /* modify switch_sel A */
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_ACTIVE_A));
    /* wait until switch ok */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_ACTIVE_A));
    /* disable rx_spare */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_set_rx_spare(lchip, group_node, FALSE));
    /* update group rx flag */
    group_node->rx.active = SYS_FLEXE_ACTIVE_A;

    /************************* RX END **************************/

    /************************* group PHY loopback clear ************************/
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_phy_static_cfg(lchip, group_node, FALSE, FALSE));
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_phy_link_intr_mask(lchip, group_node, FALSE));
    /************************* interrupt unmask ************************/

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_reset_group(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 tmp_mode = 0;

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            group_node->rx.dir_inst[i].slot_cfg_shim_chid[j] = 0;
        }
    }

    if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A))
    {
        if ((SYS_FLEXE_STATIC_SWITCH == group_node->switch_mode))
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_group_manual_reset_ohram(lchip, group_node));
            CTC_ERROR_RETURN(_sys_tmm_flexe_static_switch_lb(lchip, group_node, SYS_FLEXE_ACTIVE_A, FALSE));
        }
        else
        {
            /* disable switchen */
            CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_en(lchip, group_node, SYS_FLEXE_DIR_TX, FALSE));
            CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_en(lchip, group_node, SYS_FLEXE_DIR_RX, FALSE));
            /* modify switchsel */
            CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_ACTIVE_A));
            CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_ACTIVE_A));
            /* reset to A table when PHY unbind from group */
            tmp_mode = group_node->switch_mode;
            group_node->switch_mode = SYS_FLEXE_STATIC_SWITCH;
            CTC_ERROR_RETURN(_sys_tmm_flexe_static_switch_lb(lchip, group_node, SYS_FLEXE_ACTIVE_A, FALSE));
            group_node->switch_mode = tmp_mode;
        }
    }
    else
    {
        /* reset to A table when PHY unbind from group */
        tmp_mode = group_node->switch_mode;
        group_node->switch_mode = SYS_FLEXE_STATIC_SWITCH;
        CTC_ERROR_RETURN(_sys_tmm_flexe_static_switch_lb(lchip, group_node, SYS_FLEXE_ACTIVE_A, FALSE));
        group_node->switch_mode = tmp_mode;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_unbind_phylist(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint8 tmp_shim_id = 0;
    uint8 group_empty = TRUE;  /* value: whether group has client */

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, group %d unbind phylist\n", __FUNCTION__, __LINE__, group_node->group_id);

    /* check whether group phy list empty or not */
    if (!group_node->phy_cnt)
    {
        /* already empty, do nothing */
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] FlexE group %d is empty already!\n", group_node->group_id);
        return CTC_E_NONE;
    }

    /* check whether group has client expect rx_client */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_client_empty(lchip, group_node, &group_empty));
    if (!group_empty)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " FlexE group %d is not empty, please remove client bind to it!\n", group_node->group_id);
        return CTC_E_INVALID_PARAM;
    }

    FLEXE_DUMP("\n\n\n*************************************************************************\n");
    FLEXE_DUMP("flexe group %d property phy-list []\n", group_node->group_id);
    FLEXE_DUMP("\n*************************************************************************\n\n");

    /* reset group table to A, remove rx client */
    CTC_ERROR_RETURN(_sys_tmm_flexe_reset_group(lchip, group_node));

    /* mcu workround */
    CTC_ERROR_RETURN(_sys_tmm_flexe_unbind_phylist_adjust_afull(lchip, group_node));

    /* unbind phy hw cfg */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_hw_cfg(lchip, group_node, FALSE, FALSE));

    /* init group ds */
    tmp_shim_id = group_node->flexe_shim_id;
    CTC_ERROR_RETURN(_sys_tmm_flexe_init_group_phy_ds(lchip, group_node, TRUE));

    /* reset shim after init sw */
    CTC_ERROR_RETURN(_sys_tmm_flexe_reset_shim(lchip, tmp_shim_id));

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_FLEXE, SYS_WB_APPID_FLEXE_SUBID_GROUP, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_FLEXE, SYS_WB_APPID_FLEXE_SUBID_GROUP_MEM, 1);

    CTC_ERROR_RETURN(_sys_tmm_flexe_group_mem_mgr(lchip, group_node, 0, 0, SYS_TMM_FLEXE_MEM_MGR_OP_FREE));

    /* clear abnormal intr, then check 2 times */
    (void)_ctc_tmm_dkit_check_abnormal_intr(lchip, 1);
    (void)_ctc_tmm_dkit_check_abnormal_intr(lchip, 0);
    (void)_ctc_tmm_dkit_check_abnormal_intr(lchip, 0);

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_set_phylist(uint8 lchip, sys_flexe_group_t *group_node, ctc_flexe_phy_t *phylist)
{
    if (phylist->serdes_cnt)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_bind_phylist(lchip, group_node, phylist));
    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_unbind_phylist(lchip, group_node));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_unbind_group(uint8 lchip, sys_flexe_client_t* p_client_node)
{
    uint8 tx_have_slot = FALSE;
    uint8 rx_have_slot = FALSE;
    sys_flexe_group_t*  p_group_node  = NULL;
    sys_resource_manage_item_info_t *p_channel_arrange = p_usw_datapath_master[lchip]->resource_manage.channel_arrange;
    sys_datapath_lport_attr_t* port_attr = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    if (!p_client_node)
    {
        return CTC_E_NOT_INIT;
    }

    _sys_tmm_flexe_group_lookup(lchip, p_client_node->group_id, &p_group_node);
    if (!p_group_node)
    {
        return CTC_E_NONE;
    }

    _sys_tmm_flexe_check_client_slot(lchip, p_client_node, SYS_FLEXE_DIR_TX, &tx_have_slot);
    _sys_tmm_flexe_check_client_slot(lchip, p_client_node, SYS_FLEXE_DIR_RX, &rx_have_slot);
    if (tx_have_slot || rx_have_slot)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d not empty now! check if the slot has been removed and try again!\n",\
            p_client_node->client_id);
        return CTC_E_NOT_READY;
    }

    FLEXE_DUMP("\n\n\n*************************************************************************\n");
    FLEXE_DUMP("flexe client %d property unbind group %d\n", p_client_node->client_id, p_client_node->group_id);
    FLEXE_DUMP("\n*************************************************************************\n\n");

    /* free channel */
    p_channel_arrange[p_client_node->chan_id].using_stat = SYS_RESOURCE_FREE;
    p_client_node->chan_id        = SYS_FLEXE_UNUSED_FLAG_U8;

    p_client_node->group_id       = SYS_FLEXE_UNUSED_FLAG_U32;
    p_client_node->flexe_shim_id  = SYS_FLEXE_UNSUPP;
    p_client_node->tx_xc_chid     = SYS_FLEXE_UNUSED_FLAG_U8;
    p_client_node->rx_xc_chid     = SYS_FLEXE_UNUSED_FLAG_U8;
    p_client_node->shim_chid      = 0;

    /* set port_attr->chan_id if port exists */
    if (SYS_FLEXE_UNUSED_FLAG_U32 != p_client_node->gport)
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, CTC_MAP_GPORT_TO_LPORT(p_client_node->gport));
        if (port_attr)
        {
            port_attr->chan_id = p_client_node->chan_id;
        }
    }

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_FLEXE, SYS_WB_APPID_FLEXE_SUBID_CLIENT, 1);
    
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_bind_group(uint8 lchip, sys_flexe_client_t* p_client_node, uint32 group_id)
{
    uint8 chid_alloc = 0;
    sys_flexe_group_t*  p_group_node  = NULL;
    uint8 chan_id = 0;
    int32 ret = 0;
    sys_resource_manage_item_info_t *p_channel_arrange = p_usw_datapath_master[lchip]->resource_manage.channel_arrange;
    sys_datapath_lport_attr_t* port_attr = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    if (p_client_node->group_id == group_id)
    {
        return CTC_E_NONE;
    }

    CTC_ERROR_RETURN(_sys_tmm_flexe_client_bind_group_pc(lchip, p_client_node, group_id));

    _sys_tmm_flexe_group_lookup(lchip, group_id, &p_group_node);

    FLEXE_DUMP("\n\n\n*************************************************************************\n");
    FLEXE_DUMP("flexe client %d property group %d\n", p_client_node->client_id, group_id);
    FLEXE_DUMP("\n*************************************************************************\n\n");

    /* check whether datapath channel is free */
    ret = sys_tmm_datapath_get_idle_chanid(lchip, SYS_ARRANGE_FLEXE_PORT_BMP, p_group_node->flexe_shim_id, &chan_id);
    if (!ret)
    {
        p_channel_arrange[chan_id].using_stat = SYS_RESOURCE_IN_USE;
    }
    else
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "[FlexE] { %s @ %d } get chan ID fail, no resource\n", __FUNCTION__, __LINE__);
        return CTC_E_NO_RESOURCE;
    }

    _sys_tmm_flexe_get_free_xc_chid(lchip, p_group_node->flexe_shim_id, &chid_alloc);
    if (MCHIP_CAP(SYS_CAP_FLEXE_MAX_CLIENT) == chid_alloc)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client count reaches max, client %d failed binding group!\n", p_client_node->client_id);
        return CTC_E_INVALID_PARAM;
    }

    p_client_node->group_id      = group_id;
    p_client_node->flexe_shim_id = p_group_node->flexe_shim_id;
    p_client_node->chan_id       = chan_id;
    p_client_node->tx_xc_chid    = chid_alloc;
    p_client_node->rx_xc_chid    = chid_alloc;
    p_client_node->shim_chid     = SYS_TMM_FLEXE_CLIENT_XC_2_SHIM_CHID(chid_alloc);

    /* set port_attr->chan_id if port exists */
    if (SYS_FLEXE_UNUSED_FLAG_U32 != p_client_node->gport)
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, CTC_MAP_GPORT_TO_LPORT(p_client_node->gport));
        if (port_attr)
        {
            port_attr->chan_id = p_client_node->chan_id;
        }
    }

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_FLEXE, SYS_WB_APPID_FLEXE_SUBID_CLIENT, 1);

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_set_group(uint8 lchip, sys_flexe_client_t* p_client_node, uint32 group_id)
{
    if (SYS_FLEXE_UNUSED_FLAG_U32 == group_id)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_unbind_group(lchip, p_client_node));
    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_bind_group(lchip, p_client_node, group_id));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_send_client_cal(uint8 lchip, sys_flexe_group_t* group_node, uint8 act_flag)
{
    uint8 oh_field_type = 0;
    uint32 client_cal[SYS_FLEXE_MAX_INST_CNT][SYS_FLEXE_OH_MAX_SLOT_PER_INST] = {{0}};

    /* input value of act_flag is impossible to be SYS_FLEXE_CFG_FLAG */
    if(SYS_FLEXE_CFG_FLAG == act_flag)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] client calendar cannot base on cfg slot!\n");
        return CTC_E_INVALID_PARAM;
    }

    /* get client cal */
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_client_cal(lchip, group_node, SYS_FLEXE_DIR_TX, act_flag, client_cal));

    /* get target */
    if(SYS_FLEXE_INACTIVE_FLAG == act_flag)
    {
        oh_field_type = (SYS_FLEXE_ACTIVE_A == group_node->tx.active) ? FLEXE_OH_FIELD_TYPE_CLIENT_CAL_B : FLEXE_OH_FIELD_TYPE_CLIENT_CAL_A;
    }
    else
    {
        oh_field_type = (SYS_FLEXE_ACTIVE_A == group_node->tx.active) ? FLEXE_OH_FIELD_TYPE_CLIENT_CAL_A : FLEXE_OH_FIELD_TYPE_CLIENT_CAL_B;
    }

    /* write group ohram */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_oh(lchip, group_node, oh_field_type, (void *)client_cal));

    return CTC_E_NONE;    
}

STATIC int32
_sys_tmm_flexe_group_static_send_client_cal(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint32 client_cal[SYS_FLEXE_MAX_INST_CNT][SYS_FLEXE_OH_MAX_SLOT_PER_INST] = {{0}};

    /* get client cal */
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_client_cal(lchip, group_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_INACTIVE_FLAG, client_cal));

    /* write group ohram */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_oh(lchip, group_node, FLEXE_OH_FIELD_TYPE_CLIENT_CAL_A, (void *)client_cal));
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_oh(lchip, group_node, FLEXE_OH_FIELD_TYPE_CLIENT_CAL_B, (void *)client_cal));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_client_number(uint8 lchip, sys_flexe_client_t* p_client_node, uint32 client_number)
{
    sys_flexe_group_t*  group_node  = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    if (!p_client_node)
    {
        return CTC_E_NOT_INIT;
    }

    if (client_number > SYS_FLEXE_MAX_CLIENT_NUM || client_number == 0)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] client_number must be between 1 and 0xfffe!\n");
        return CTC_E_INVALID_PARAM;
    }

    /* Check whether the client number is same with the client's client number */
    if (client_number == p_client_node->client_number)
    {
        return CTC_E_NONE;
    }

    _sys_tmm_flexe_group_lookup(lchip, p_client_node->group_id, &group_node);
    if (!group_node)
    {
        p_client_node->client_number = client_number;
        return CTC_E_NONE;
    }
    else
    {
        /* Check whether client's client number is same with other clients in the group */
        CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_client_number_same(lchip, client_number, group_node->group_id));

        p_client_node->client_number = client_number;

        /* write client cal */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_send_client_cal(lchip, group_node, SYS_FLEXE_INACTIVE_FLAG));
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_send_client_cal(lchip, group_node, SYS_FLEXE_ACTIVE_FLAG));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_client_mac_en(uint8 lchip, sys_flexe_client_t* client_node, uint8 enable)
{
    if (SYS_FLEXE_UNUSED_FLAG_U16 != client_node->mac_id)
    {
        CTC_ERROR_RETURN(_sys_tmm_mac_set_flexe_mac_en(lchip, client_node->mac_id, SYS_FLEXE_DIR_RX, enable));
        CTC_ERROR_RETURN(_sys_tmm_mac_set_flexe_mac_en(lchip, client_node->mac_id, SYS_FLEXE_DIR_TX, enable));
        if (SYS_FLEXE_UNUSED_FLAG_U32 != client_node->gport)
        {
            p_usw_mac_master[lchip]->mac_prop[CTC_MAP_GPORT_TO_LPORT(client_node->gport)].port_mac_en = enable ? 1 : 0;
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_free_lport(uint8 lchip, sys_flexe_client_t *client_node)
{
    uint16 lport   = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;
    sys_resource_manage_item_info_t *p_lport_arrange   = p_usw_datapath_master[lchip]->resource_manage.lport_arrange;

    if (2 != client_node->aps_role)
    {
        lport = CTC_MAP_GPORT_TO_LPORT(client_node->gport);
        port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
        if (!port_attr)
        {
            return CTC_E_NO_MEMORY;
        }
        _sys_tmm_datapath_clear_port_attr(lchip, lport);
        p_lport_arrange[lport].using_stat = SYS_RESOURCE_FREE;
        CTC_ERROR_RETURN(sys_usw_add_port_to_channel(lchip, lport, MCHIP_CAP(SYS_CAP_CHANID_DROP), 0));
    }
    client_node->gport = SYS_FLEXE_UNUSED_FLAG_U32;
    client_node->flow_type = SYS_FLEXE_FLOW_MAX;

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_aps(uint8 lchip, sys_flexe_client_t* client_node, uint16 lport, sys_datapath_lport_attr_t* port_attr, uint8 enable)
{
    if (SYS_FLEXE_UNUSED_FLAG_U16 == port_attr->mac_id)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Client %d gport %d working mac not exists!\n", client_node->client_id, client_node->gport);
        return CTC_E_INVALID_PARAM;
    }
    if (SYS_FLEXE_UNUSED_FLAG_U16 == port_attr->mac_id_aps)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Client %d gport %d protected mac not exists!\n", client_node->client_id, client_node->gport);
        return CTC_E_INVALID_PARAM;
    }
    CTC_ERROR_RETURN(_sys_tmm_flexe_client_aps_en(lchip, port_attr->mac_id, port_attr->mac_id_aps, enable));
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_unbind_port(uint8 lchip, sys_flexe_client_t** pp_client_node)
{
    uint8 active_cnt = 0;
    uint16 lport = 0;    
    uint32 intr_stat = 0;
    uint32 tx_rx_en = 0;    
    sys_flexe_client_t* client_node = *pp_client_node;
    sys_datapath_lport_attr_t* port_attr = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, client %d unbind port %d\n", __FUNCTION__, __LINE__, client_node->client_id, client_node->gport);

    if (SYS_FLEXE_UNUSED_FLAG_U32 == client_node->gport)
    {
        /* not bind yet, do nothing */
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] client not binded to port, no need to unbind\n");
        return CTC_E_NONE;
    }

    lport = CTC_MAP_GPORT_TO_LPORT(client_node->gport);
    port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
    if (!port_attr)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Client %d gport %d not exist!\n", client_node->client_id, client_node->gport);
        return CTC_E_INVALID_PARAM;
    }

    if ((1 == client_node->aps_role) && (2 == port_attr->client_bind_num))
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] FlexE APS working client %d CANNOT unbind port %d!\n", client_node->client_id, client_node->gport);
        return CTC_E_INVALID_CONFIG;
    }

    if (SYS_DMPS_RSV_PORT != port_attr->port_type)
    {
        /* disable interrupt */
        CTC_ERROR_RETURN(_sys_tmm_mac_get_link_intr(lchip, lport, &intr_stat));
        if(0 != intr_stat)
        {
            CTC_ERROR_RETURN(_sys_tmm_mac_set_link_intr(lchip, lport, FALSE));
        }

        /* disable client mac */
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_client_mac_en(lchip, client_node, FALSE));

        /* enable interrupt after operation */
        if(0 != intr_stat)
        {
            CTC_ERROR_RETURN(_sys_tmm_mac_set_link_intr(lchip, lport, TRUE));
        }
    }

    if (2 == client_node->aps_role)  /* protected client */
    {
        /* Must locate before datapath update! */
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_aps(lchip, client_node, lport, port_attr, 0));
        /*default enable working client*/
        tx_rx_en = 0x3;
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_set_mcmac_tx_rx_en(lchip, &client_node, tx_rx_en));        
        port_attr->client_bind_num = 1;
    }
    else
    {
        if (SYS_FLEXE_UNUSED_FLAG_U16 != client_node->mac_id)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_mac_prop_clear(lchip, lport, client_node->mac_id));
        }
        port_attr->client_bind_num = 0;
    }

    _sys_tmm_flexe_get_client_slot_cnt(lchip, client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_ACTIVE_FLAG, &active_cnt);
    if (active_cnt)
    {
        if (2 == client_node->aps_role)  /* protected client */
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_client_set_datapath_main(lchip, client_node, TRUE));
        }
        else
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_client_set_datapath_main(lchip, client_node, FALSE));
        }
    }

    CTC_ERROR_RETURN(_sys_tmm_flexe_client_free_lport(lchip, client_node));
    client_node->aps_role = 0;

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_bind_port(uint8 lchip, sys_flexe_client_t* client_node, uint32 gport)
{
    uint8 active_cnt        = 0;
    uint8 aps_cfg_flag      = 0;
    uint16 lport            = 0;
    uint32 tx_speed         = 0;
    uint32 tx_speed_aps     = 0;
    uint32 rx_speed         = 0;
    uint32 rx_speed_aps     = 0;
    int32 ret               = CTC_E_NONE;
    sys_flexe_client_t* client_node_aps = NULL;
    sys_resource_manage_item_info_t *p_lport_arrange   = p_usw_datapath_master[lchip]->resource_manage.lport_arrange;
    sys_datapath_lport_attr_t* port_attr = NULL;
    uint32 tx_rx_en = 0;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, client %d bind gport %d\n", __FUNCTION__, __LINE__, client_node->client_id, gport);

    if (SYS_FLEXE_UNUSED_FLAG_U32 == gport)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_unbind_port(lchip, &client_node));
        return CTC_E_NONE;
    }

    if (gport == client_node->gport)
    {
        return CTC_E_NONE;
    }

    if (client_node->gport != SYS_FLEXE_UNUSED_FLAG_U32)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FLEXE] Client %d already binded to gport %d\n", client_node->client_id, client_node->gport);
        return CTC_E_EXIST;
    }
    if (client_node->cross_enable)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client %d has configureed L1 cross, CANNOT bind port!\n", client_node->client_id);
        return CTC_E_INVALID_PARAM;
    }

    FLEXE_DUMP("\n\n\n*************************************************************************\n");
    FLEXE_DUMP("flexe client %d property port %d\n", client_node->client_id, gport);
    FLEXE_DUMP("\n*************************************************************************\n\n");

    lport = CTC_MAP_GPORT_TO_LPORT(gport);
    if (TRUE == p_lport_arrange[lport].using_stat)
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
        if (port_attr && (CTC_PORT_IF_FLEXE != port_attr->interface_type))
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FLEXE] Lport %d is being used\n", lport);
            return CTC_E_IN_USE;
        }
    }

    port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
    if (!port_attr)
    {
        return CTC_E_NO_MEMORY;
    }

    if (port_attr->client_bind_num >= 2)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FLEXE] Lport %d is being used by other FlexE client\n", lport);
        return CTC_E_EXIST;
    }

    if (1 == port_attr->client_bind_num)
    {
        /* lookup working client */
        _sys_tmm_flexe_client_lookup(lchip, port_attr->flexe_client, &client_node_aps);
        if (NULL == client_node_aps)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FLEXE] Lport %d is in aps, but can't find the other aps client\n", lport);
            return CTC_E_NOT_EXIST;
        }
        if ((client_node_aps->mac_id / SYS_TMM_MAX_MAC_NUM_PER_TXQM != client_node->mac_id / SYS_TMM_MAX_MAC_NUM_PER_TXQM))
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FLEXE] client %d mac %d and client %d mac %d are not in the same TXQM, CANNOT config FlexE APS!\n", \
                client_node->client_id, client_node->mac_id, client_node_aps->client_id, client_node_aps->mac_id);
            return CTC_E_INVALID_CONFIG;
        }
        /* check client active speed */
        _sys_tmm_flexe_get_client_speed_val(lchip, client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_ACTIVE_FLAG, &tx_speed);
        _sys_tmm_flexe_get_client_speed_val(lchip, client_node_aps, SYS_FLEXE_DIR_TX, SYS_FLEXE_ACTIVE_FLAG, &tx_speed_aps);
        if (!tx_speed || !tx_speed_aps || (tx_speed != tx_speed_aps))
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client %d tx speed %d and client %d tx speed %d are not same active value, CANNOT config FlexE APS!\n", \
                client_node->client_id, tx_speed, client_node_aps->client_id, tx_speed_aps);
            return CTC_E_INVALID_CONFIG;
        }
        _sys_tmm_flexe_get_client_speed_val(lchip, client_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_ACTIVE_FLAG, &rx_speed);
        _sys_tmm_flexe_get_client_speed_val(lchip, client_node_aps, SYS_FLEXE_DIR_RX, SYS_FLEXE_ACTIVE_FLAG, &rx_speed_aps);
        if (!rx_speed || !rx_speed_aps || (rx_speed != rx_speed_aps))
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client %d rx speed %d and client %d rx speed %d are not same active value, CANNOT config FlexE APS!\n", \
                client_node->client_id, rx_speed, client_node_aps->client_id, rx_speed_aps);
            return CTC_E_INVALID_CONFIG;
        }
    }

    ret = _sys_tmm_flexe_client_set_port_attr(lchip, client_node, lport);
    p_lport_arrange[lport].using_stat = SYS_RESOURCE_IN_USE;
    if (ret)
    {
        p_lport_arrange[lport].using_stat = SYS_RESOURCE_FREE;
        return ret;
    }

    client_node->gport = gport;
    client_node->flow_type = SYS_FLEXE_FLOW_TYPE_B;

    if (1 == port_attr->client_bind_num)
    {
        aps_cfg_flag = 1;
        port_attr->client_bind_num = 2;
        client_node->aps_role = 2;  /* update protected client aps role */
        /* lookup working client */
        _sys_tmm_flexe_client_lookup(lchip, port_attr->flexe_client, &client_node_aps);
        if (client_node_aps)
        {
            client_node_aps->aps_role = 1;  /* update working client aps role */
        }
    }
    else if (0 == port_attr->client_bind_num)
    {
        port_attr->client_bind_num = 1;
    }

    _sys_tmm_flexe_get_client_slot_cnt(lchip, client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_ACTIVE_FLAG, &active_cnt);
    if (active_cnt)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_set_datapath_main(lchip, client_node, TRUE));
    }

    /* set mac rx pkt enable */
    CTC_ERROR_RETURN(_sys_tmm_mac_set_mac_rx_en(lchip, client_node->mac_id, 1));
    if (aps_cfg_flag)
    {
        /* Must locate after datapath update! */
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_aps(lchip, client_node, lport, port_attr, TRUE));

        /*default enable working client, disable protect client*/
        tx_rx_en = 0x3;
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_set_mcmac_tx_rx_en(lchip, &client_node_aps, tx_rx_en));
        tx_rx_en = 0x1;
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_set_mcmac_tx_rx_en(lchip, &client_node, tx_rx_en));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_set_mac(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_client_t* client_node, uint16 mac_id)
{
    sys_datapath_lport_attr_t* port_attr = NULL;
    sys_resource_manage_item_info_t *p_macid_arrange = p_usw_datapath_master[lchip]->resource_manage.macid_arrange;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    p_macid_arrange[mac_id].using_stat = SYS_RESOURCE_IN_USE;
    client_node->mac_id = mac_id;
    if (SYS_FLEXE_UNUSED_FLAG_U32 != client_node->gport)
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, CTC_MAP_GPORT_TO_LPORT(client_node->gport));
        if (!port_attr)
        {
            return CTC_E_NO_MEMORY;
        }
        if (1 == port_attr->client_bind_num)
        {
            port_attr->mac_id           = mac_id;
            port_attr->internal_mac_idx = SYS_TMM_GET_MACID_PER_TXQM(port_attr->mac_id);
            port_attr->txqm_id          = port_attr->mac_id / SYS_TMM_MAX_MAC_NUM_PER_TXQM;
        }
        else if (2 == port_attr->client_bind_num)
        {
            port_attr->mac_id_aps = mac_id;
        }
        port_attr->port_type = SYS_DMPS_NETWORK_PORT;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_free_mac(uint8 lchip, sys_flexe_client_t *client_node)
{
    sys_resource_manage_item_info_t *p_macid_arrange   = p_usw_datapath_master[lchip]->resource_manage.macid_arrange;
    sys_datapath_lport_attr_t* port_attr = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    SYS_CONDITION_RETURN((320 <= client_node->mac_id), CTC_E_INVALID_PARAM);

    if (SYS_FLEXE_UNUSED_FLAG_U32 != client_node->gport)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_mac_prop_clear(lchip, CTC_MAP_GPORT_TO_LPORT(client_node->gport), client_node->mac_id));
    }

    p_macid_arrange[client_node->mac_id].using_stat = SYS_RESOURCE_FREE;
    FLEXE_DBG_PRINTF("free client %d mac %d\n", client_node->client_id, client_node->mac_id);
    client_node->mac_id = SYS_FLEXE_UNUSED_FLAG_U16;

    if (SYS_FLEXE_UNUSED_FLAG_U32 != client_node->gport)
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, CTC_MAP_GPORT_TO_LPORT(client_node->gport));
        if (!port_attr)
        {
            return CTC_E_NO_MEMORY;
        }
        if (1 == port_attr->client_bind_num)
        {
            port_attr->mac_id     = client_node->mac_id;
            port_attr->port_type  = SYS_DMPS_RSV_PORT;
        }
        else if (2 == port_attr->client_bind_num)
        {
            port_attr->mac_id_aps = client_node->mac_id;
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_slot_cfg2switch(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir)
{
    uint8 i = 0;
    uint8 j = 0;

    sys_flexe_group_dir_t *p_group_dir = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    if (SYS_FLEXE_ACTIVE_A == p_group_dir->active)
    {
        for (i = 0; i < group_node->inst_cnt; i++)
        {
            for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
            {
                p_group_dir->dir_inst[i].switch_shim_chid_b[j] = p_group_dir->dir_inst[i].slot_cfg_shim_chid[j];
            }
        }
    }
    else
    {
        for (i = 0; i < group_node->inst_cnt; i++)
        {
            for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
            {
                p_group_dir->dir_inst[i].switch_shim_chid_a[j] = p_group_dir->dir_inst[i].slot_cfg_shim_chid[j];
            }
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_slot_active2cfg(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir)
{
    uint8 i = 0;
    uint8 j = 0;

    sys_flexe_group_dir_t *p_group_dir = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    if (SYS_FLEXE_ACTIVE_A == p_group_dir->active)
    {
        for (i = 0; i < group_node->inst_cnt; i++)
        {
            for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
            {
                p_group_dir->dir_inst[i].slot_cfg_shim_chid[j] = p_group_dir->dir_inst[i].switch_shim_chid_a[j];
            }
        }
    }
    else
    {
        for (i = 0; i < group_node->inst_cnt; i++)
        {
            for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
            {
                p_group_dir->dir_inst[i].slot_cfg_shim_chid[j] = p_group_dir->dir_inst[i].switch_shim_chid_b[j];
            }
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_switch_slot_sync(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir)
{
    uint8 i = 0;
    uint8 j = 0;

    sys_flexe_group_dir_t *p_group_dir = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    if (SYS_FLEXE_ACTIVE_A == p_group_dir->active)
    {
        for (i = 0; i < group_node->inst_cnt; i++)
        {
            for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
            {
                p_group_dir->dir_inst[i].switch_shim_chid_b[j] = p_group_dir->dir_inst[i].switch_shim_chid_a[j];
            }
        }
    }
    else
    {
        for (i = 0; i < group_node->inst_cnt; i++)
        {
            for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
            {
                p_group_dir->dir_inst[i].switch_shim_chid_a[j] = p_group_dir->dir_inst[i].switch_shim_chid_b[j];
            }
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_sync(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 cnt = 0;
    uint8 slot = 0;
    uint8 asic_inst = 0;
    uint32 inst_mask = 0;
    uint8 client_cycle_list[SYS_FLEXE_MAX_CYCLE];
    sys_flexe_group_dir_t *p_group_dir = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    /* sync switch slot */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_switch_slot_sync(lchip, group_node, dir));

    /* sync inst sch config */
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        asic_inst = group_node->inst_list[i];
        inst_mask |= 1 << asic_inst;
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            slot = asic_inst * MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) + j;
            client_cycle_list[cnt] = (slot%MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST)) * MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT) + slot/MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST);
            cnt++;
        }
        CTC_ERROR_RETURN(_sys_tmm_flexe_inst_sch_config_sync(lchip, group_node->flexe_shim_id, p_group_dir->active, asic_inst, dir));
    }

    /* sync client sch config */
    for (i = 0; i < cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); j++)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_client_sch_config_sync(lchip, group_node->flexe_shim_id, j, p_group_dir->active, client_cycle_list[i], dir));
        }
    }

    /* sync client en */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_inst_bmp_sync(lchip, group_node->flexe_shim_id, p_group_dir->active, inst_mask, dir));
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        asic_inst = group_node->inst_list[i];
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_inst_subcal_sync(lchip, group_node->flexe_shim_id, p_group_dir->active, asic_inst, dir));
    }

    /* sync client cal */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_send_client_cal(lchip, group_node, SYS_FLEXE_INACTIVE_FLAG));

    /* flush clear */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config_clear(lchip, group_node, dir));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_cfg_slot_update(uint8 lchip, sys_flexe_client_t* client_node, sys_flexe_dir_t dir, ctc_flexe_client_slot_t* p_slot)
{
    uint8 i = 0, j = 0, k = 0;
    uint8 slot_per_inst = 0;
    uint8 group_inst_base = 0;
    uint8 group_inst_offset = 0;
    uint8 logical_serdes_id = 0;
    sys_flexe_group_t*  group_node  = NULL;
    sys_flexe_phy_t*    phy_node = NULL;
    sys_flexe_group_dir_t *p_group_dir = NULL;

    _sys_tmm_flexe_group_lookup(lchip, client_node->group_id, &group_node);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group ID %d not exist!\n", client_node->group_id);
        return CTC_E_NOT_EXIST;
    }

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    /* clear slot_cfg_shim_chid, if shim_chid is same with client's shim_chid */
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            if (client_node->shim_chid == p_group_dir->dir_inst[i].slot_cfg_shim_chid[j])
            {
                p_group_dir->dir_inst[i].slot_cfg_shim_chid[j] = 0;
            }
        }
    }

    /* update slot_cfg_shim_chid */
    for (i = 0; i < p_slot->phy_cnt; i++)
    {
        _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)p_slot->slot[i].serdes_id, &logical_serdes_id);
        SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
        phy_node = _sys_tmm_flexe_get_phy_node(lchip, logical_serdes_id);
        if (!phy_node)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] logical_serdes ID %d is not used by any phy\n", logical_serdes_id);
            return CTC_E_NOT_EXIST;
        }

        for (k = 0; k < group_node->inst_cnt; k++)
        {
            if (phy_node->inst_base == group_node->inst_list[k])
            {
                group_inst_base = k;
                break;
            }
        }

        switch (phy_node->pcs_mode)
        {
        case CTC_CHIP_SERDES_LG_MODE:
        case CTC_CHIP_SERDES_LG_R1_MODE:
            for (j = 0; j < SYS_FLEXE_INSTANCE_SLOT_50G_NUM; j++)
            {
                group_inst_offset = group_inst_base;
                slot_per_inst = j;
                if (CTC_BMP_ISSET(p_slot->slot[i].slot_bmp, j))
                {
                    p_group_dir->dir_inst[group_inst_offset].slot_cfg_shim_chid[slot_per_inst] = client_node->shim_chid;
                }
                else
                {
                    if (client_node->shim_chid == p_group_dir->dir_inst[group_inst_offset].slot_cfg_shim_chid[slot_per_inst])
                    {
                        p_group_dir->dir_inst[group_inst_offset].slot_cfg_shim_chid[slot_per_inst] = 0;
                    }
                }
            }
            break;
        case CTC_CHIP_SERDES_CG_MODE:
        case CTC_CHIP_SERDES_CG_R2_MODE:
            for (j = 0; j < SYS_FLEXE_INSTANCE_SLOT_100G_NUM; j++)
            {
                group_inst_offset = group_inst_base + j % 2;
                slot_per_inst = j / 2;
                if (CTC_BMP_ISSET(p_slot->slot[i].slot_bmp, j))
                {
                    p_group_dir->dir_inst[group_inst_offset].slot_cfg_shim_chid[slot_per_inst] = client_node->shim_chid;
                }
                else
                {
                    if (client_node->shim_chid == p_group_dir->dir_inst[group_inst_offset].slot_cfg_shim_chid[slot_per_inst])
                    {
                        p_group_dir->dir_inst[group_inst_offset].slot_cfg_shim_chid[slot_per_inst] = 0;
                    }
                }
            }
            break;
        case CTC_CHIP_SERDES_CCG_R4_MODE:
            for (j = 0; j < SYS_FLEXE_INSTANCE_SLOT_200G_NUM; j++)
            {
                group_inst_offset = group_inst_base + j % 2 + (j / SYS_FLEXE_INSTANCE_SLOT_100G_NUM) * 2;
                slot_per_inst = (j % SYS_FLEXE_INSTANCE_SLOT_100G_NUM) / 2;
                if (CTC_BMP_ISSET(p_slot->slot[i].slot_bmp, j))
                {
                    p_group_dir->dir_inst[group_inst_offset].slot_cfg_shim_chid[slot_per_inst] = client_node->shim_chid;
                }
                else
                {
                    if (client_node->shim_chid == p_group_dir->dir_inst[group_inst_offset].slot_cfg_shim_chid[slot_per_inst])
                    {
                        p_group_dir->dir_inst[group_inst_offset].slot_cfg_shim_chid[slot_per_inst] = 0;
                    }
                }
            }
            break;
        case CTC_CHIP_SERDES_CDG_R8_MODE:
            for (j = 0; j < SYS_FLEXE_INSTANCE_SLOT_400G_NUM; j++)
            {
                group_inst_offset = group_inst_base + j % 2 + (j / SYS_FLEXE_INSTANCE_SLOT_100G_NUM) * 2;
                slot_per_inst = (j % SYS_FLEXE_INSTANCE_SLOT_100G_NUM) / 2;
                if (CTC_BMP_ISSET(p_slot->slot[i].slot_bmp, j))
                {
                    p_group_dir->dir_inst[group_inst_offset].slot_cfg_shim_chid[slot_per_inst] = client_node->shim_chid;
                }
                else
                {
                    if (client_node->shim_chid == p_group_dir->dir_inst[group_inst_offset].slot_cfg_shim_chid[slot_per_inst])
                    {
                        p_group_dir->dir_inst[group_inst_offset].slot_cfg_shim_chid[slot_per_inst] = 0;
                    }
                }
            }
            break;
        default:
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] Unsupported PCS mode %d \n", phy_node->pcs_mode);
            return CTC_E_INVALID_PARAM;
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_flexe_client_txrx_bind_slot(uint8 lchip, sys_flexe_client_t* client_node, sys_flexe_dir_t dir, ctc_flexe_client_slot_t* p_slot)
{
    uint8  i              = 0;
    uint8  j              = 0;
    uint8  user_slot_cnt  = 0;
    uint8  tx_have_slot   = FALSE;
    uint8  rx_have_slot   = FALSE;
    uint16 alloced_mac_id = SYS_FLEXE_UNUSED_FLAG_U16;
    sys_flexe_group_t* group_node  = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, set client %d slot\n", __FUNCTION__, __LINE__, client_node->client_id);

    /* param check */
    CTC_ERROR_RETURN(_sys_tmm_flexe_client_bind_slot_pc(lchip, client_node, dir, p_slot));

    /* get group */
    _sys_tmm_flexe_group_lookup(lchip, client_node->group_id, &group_node);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group ID %d not exist!\n", client_node->group_id);
        return CTC_E_NOT_EXIST;
    }

    /* alloc mac_id */
    for (i = 0; i < p_slot->phy_cnt; i++)
    {
        for (j = 0; j < CTC_FLEXE_INSTANCE_SLOT_NUM; j++)
        {
            if (CTC_BMP_ISSET(p_slot->slot[i].slot_bmp, j))
            {
                user_slot_cnt++;
            }
        }
    }
    if (SYS_FLEXE_UNUSED_FLAG_U16 == client_node->mac_id)
    {
        if (user_slot_cnt)
        {
            /* Client without mac will try to alloc mac_id */
            CTC_ERROR_RETURN(_sys_tmm_flexe_client_alloc_mac_check(lchip, group_node, client_node, user_slot_cnt, dir, &alloced_mac_id));
        }
    }

    /* update group software table */
    CTC_ERROR_RETURN(_sys_tmm_flexe_client_cfg_slot_update(lchip, client_node, dir, p_slot));

    /* set or free mac */
    if (SYS_FLEXE_UNUSED_FLAG_U16 == client_node->mac_id)
    {
        if (user_slot_cnt)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_client_set_mac(lchip, group_node, client_node, alloced_mac_id));
        }
    }
    else
    {
        _sys_tmm_flexe_check_client_slot(lchip, client_node, SYS_FLEXE_DIR_TX, &tx_have_slot);
        _sys_tmm_flexe_check_client_slot(lchip, client_node, SYS_FLEXE_DIR_RX, &rx_have_slot);
        if (!tx_have_slot && !rx_have_slot)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_client_free_mac(lchip, client_node));
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_bind_slot(uint8 lchip, sys_flexe_client_t* client_node, ctc_flexe_client_slot_t* p_slot)
{
    if (CTC_IS_BIT_SET(p_slot->flag, 0))
    {
        if (CTC_IS_BIT_SET(p_slot->flag, 1))
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_client_force_clear(lchip, client_node, SYS_FLEXE_DIR_RX));
        }
        if (CTC_IS_BIT_SET(p_slot->flag, 2))
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_client_force_clear(lchip, client_node, SYS_FLEXE_DIR_TX));
        }        
    }
    else
    {
        CTC_ERROR_RETURN(_sys_flexe_client_txrx_bind_slot(lchip, client_node, SYS_FLEXE_DIR_TX, p_slot));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_slot_change_calc(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, sys_flexe_slot_change_t* p_slot_change)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 slot = 0;
    sys_flexe_group_dir_t *p_group_dir = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    if (SYS_FLEXE_ACTIVE_A == p_group_dir->active)
    {
        for (i = 0; i < group_node->inst_cnt; i++)
        {
            for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
            {
                slot = group_node->inst_list[i]*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) + j;
                p_slot_change->slot[slot].shim_chid_new = p_group_dir->dir_inst[i].switch_shim_chid_b[j];
                p_slot_change->slot[slot].shim_chid_old = p_group_dir->dir_inst[i].switch_shim_chid_a[j];
                if ((p_group_dir->dir_inst[i].switch_shim_chid_b[j]) && (p_group_dir->dir_inst[i].switch_shim_chid_a[j]))
                {
                    p_slot_change->slot[slot].change = SYS_FLEXE_SLOT_FIX;
                }
                else if ((p_group_dir->dir_inst[i].switch_shim_chid_b[j]) && (p_group_dir->dir_inst[i].switch_shim_chid_a[j] == 0))
                {
                    p_slot_change->slot[slot].change = SYS_FLEXE_SLOT_ADD;
                }
                else if ((p_group_dir->dir_inst[i].switch_shim_chid_b[j] == 0) && (p_group_dir->dir_inst[i].switch_shim_chid_a[j]))
                {
                    p_slot_change->slot[slot].change = SYS_FLEXE_SLOT_REMOVE;
                }
                else
                {
                    p_slot_change->slot[slot].change = SYS_FLEXE_SLOT_MAX;
                }
            }
        }
    }
    else
    {
        for (i = 0; i < group_node->inst_cnt; i++)
        {
            for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
            {
                slot = group_node->inst_list[i]*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) + j;
                p_slot_change->slot[slot].shim_chid_new = p_group_dir->dir_inst[i].switch_shim_chid_a[j];
                p_slot_change->slot[slot].shim_chid_old = p_group_dir->dir_inst[i].switch_shim_chid_b[j];
                if ((p_group_dir->dir_inst[i].switch_shim_chid_a[j]) && (p_group_dir->dir_inst[i].switch_shim_chid_b[j]))
                {
                    p_slot_change->slot[slot].change = SYS_FLEXE_SLOT_FIX;
                }
                else if ((p_group_dir->dir_inst[i].switch_shim_chid_a[j]) && (p_group_dir->dir_inst[i].switch_shim_chid_b[j] == 0))
                {
                    p_slot_change->slot[slot].change = SYS_FLEXE_SLOT_ADD;
                }
                else if ((p_group_dir->dir_inst[i].switch_shim_chid_a[j] == 0) && (p_group_dir->dir_inst[i].switch_shim_chid_b[j]))
                {
                    p_slot_change->slot[slot].change = SYS_FLEXE_SLOT_REMOVE;
                }
                else
                {
                    p_slot_change->slot[slot].change = SYS_FLEXE_SLOT_MAX;
                }
            }
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_flush_gen(uint8 lchip, sys_flexe_group_t* group_node, uint8 dir)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 slot = 0;

    sys_flexe_group_dir_t *p_group_dir = NULL;
    sys_flexe_slot_change_t slot_change;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    sal_memset(&slot_change, 0, sizeof(sys_flexe_slot_change_t));

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    /* compare cfg_slot and switch_slot */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_slot_change_calc(lchip, group_node, dir, &slot_change));

    /* clear flush bmp */
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        p_group_dir->dir_inst[i].flush_bmp = 0;
    }

    /* if slot's shim_chid change, set flush bit value 1 */
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            slot = group_node->inst_list[i]*10 + j;
            if (slot_change.slot[slot].shim_chid_new != slot_change.slot[slot].shim_chid_old)
            {
                p_group_dir->dir_inst[i].flush_bmp |= (1 << j);
            }
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_subcalmask_gen(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_client_t* client_node, sys_flexe_dir_t dir, sys_flexe_slot_change_t* p_slot_change)
{
    uint8 j                 = 0;
    uint8 slot              = 0;
    uint8 slot_heng         = 0;
    //uint8 cycle_value       = 0;
    uint8 cc_client         = 0;  /* client cycle index, range: in a client, not cycle value */
    uint8 cc_group          = 0;  /* client cycle index, range: in a group, not cycle value */
    uint8 slot_cnt          = 0;
    uint8 slot_sel          = 0;
    uint8 ins_id            = 0;
    uint8 group_inst_offset = 0;
    uint8 client_slot_ptr   = 0;
    uint8 speed_mode        = 0;
    uint8 tmp               = 0;
    int8  si                = 0;  /* signed index, for inverted loop */
    int32 ret               = CTC_E_NONE;
    uint32 i                = 0;
    uint32 loop_num         = 0;
    uint8 cc_list[SYS_FLEXE_MAX_CYCLE] = {0};  /* client cycle list, index: client cycle index in a client, val : client cycle index in a group */
    uint8 client_slot[SYS_FLEXE_INSTANCE_SLOT_400G_NUM] = {0};
    uint8 ins_mask[SYS_FLEXE_MAX_INST_CNT] = {0};

    sys_flexe_group_dir_t *p_group_dir = NULL;

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            slot = group_node->inst_list[i]*10 + j;
            if (client_node->shim_chid == p_slot_change->slot[slot].shim_chid_new)
            {
                if ((0 == p_slot_change->slot[slot].change) || (1 == p_slot_change->slot[slot].change)) // 0-fix, 1-add, 2-remove, 3-none
                {
                    (void)_sys_tmm_flexe_slot_shu2heng(lchip, group_node, slot, &slot_heng);
                    client_slot[slot_cnt++] = slot_heng;
                }
            }
        }
    }

    /* cal cc_list */
    for (cc_group = 0; cc_group < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); cc_group++)
    {
        if (p_group_dir->cc[cc_group].shim_chid == client_node->shim_chid)
        {
            cc_list[cc_client++] = cc_group;
        }
    }

    /* sort client_slot[] by slot_heng, small to big */
    if (slot_cnt >= 2)
    {
        for (i = 0; i < slot_cnt-1; i++)
        {
            for (j = 0; j < slot_cnt-1-i; j++)
            {
                if (client_slot[j] > client_slot[j+1])
                {
                    tmp = client_slot[j];
                    client_slot[j] = client_slot[j+1];
                    client_slot[j+1] = tmp;
                }
            }
        }
    }

    /*
     * loop is 2-d array, each row has SYS_FLEXE_CLIENT_NUM_BLOCKS(aka: 8) 66bit blocks,
     *   row num is cycle num;
     *   GEN algorithm dispatches 8 blocks to related instances.
     */
    loop_num = slot_cnt * SYS_FLEXE_CLIENT_NUM_BLOCKS;
    cc_client = 0;

    for (i = 0; i < loop_num; i++)
    {
        if (slot_cnt == client_slot_ptr)
        {
            client_slot_ptr = 0;
        }
        slot_sel = client_slot[client_slot_ptr];

         _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);
        if (CTC_PORT_SPEED_50G != speed_mode)
        {
            ins_id = slot_sel / SYS_FLEXE_INSTANCE_SLOT_100G_NUM * 2;
            ins_id += slot_sel % 2;
        }
        else
        {
            ins_id = slot_sel / SYS_FLEXE_INSTANCE_SLOT_50G_NUM;
        }
        ins_mask[ins_id] |= (1 << (i % SYS_FLEXE_CLIENT_NUM_BLOCKS));

        client_slot_ptr++;

        if ((SYS_FLEXE_CLIENT_NUM_BLOCKS-1) == i % SYS_FLEXE_CLIENT_NUM_BLOCKS)
        {
            /* 8 blocks dispatch complete, then GEN subcalMask per instance */
            for (si = MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT) - 1; si >= 0; si--)
            {
                ret = _sys_tmm_flexe_get_group_inst_offset_by_asic_inst(lchip, group_node, si, &group_inst_offset);
                SYS_CONDITION_CONTINUE(0 != ret);
                cc_group = cc_list[cc_client];
                p_group_dir->cc[cc_group].inst[group_inst_offset].cc_subcalmask = ins_mask[si];
                ins_mask[si] = 0;
            }
            cc_client++;
        }
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_sch_gen(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, sys_flexe_slot_change_t* p_slot_change)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 slot = 0;
    uint8 slot_heng = 0;
    uint8 slot_shu = 0;
    uint8 related_slot_cnt = 0; 
    uint8 cc = 0; /* client cycle index */
    uint8 cycle_num_valid = 0;
    uint8 slot_cnt = 0;
    uint8 xc_chid = 0;
    uint8 group_slot_cnt = 0;
    uint32 tmp = 0;
    int32  ret = CTC_E_NONE;

    int32 *cycle_list = NULL;
    ctc_slistnode_t* node = NULL;
    sys_flexe_client_t* tmp_client_node = NULL;
    sys_flexe_group_dir_t *p_group_dir = NULL;

    if (0 == group_node->inst_cnt)
    {
        return CTC_E_NONE;
    }
    
    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    group_slot_cnt = MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) * group_node->inst_cnt;
    cycle_list = (int32*)mem_malloc(MEM_DMPS_MODULE, sizeof(int32)*group_slot_cnt);
    if (!cycle_list)
    {
        return CTC_E_NO_MEMORY;
    }

    sal_memset(cycle_list, 0, sizeof(uint32)*group_slot_cnt);

    /* cycle_num_valid, only include exist slot */
    related_slot_cnt = 0;
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            slot = group_node->inst_list[i]*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) + j;
            if ((SYS_FLEXE_SLOT_FIX == p_slot_change->slot[slot].change) || (SYS_FLEXE_SLOT_ADD == p_slot_change->slot[slot].change))
            {
                related_slot_cnt++;
            }
        }
    }
    cycle_num_valid = related_slot_cnt;

    /* cycle_list */
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            slot = group_node->inst_list[i]*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) + j;
            if ((0 == p_slot_change->slot[slot].change) || (1 == p_slot_change->slot[slot].change)) // 0-fix, 1-add, 2-remove, 3-none
            {
                (void)_sys_tmm_flexe_slot_shu2heng(lchip, group_node, slot, &slot_heng);
                cycle_list[cc] = SYS_TMM_FLEXE_GET_CLIENT_CYCLE(slot_heng);
                cc++;
            }
        }
    }

    /* bubble sort */
    if (cycle_num_valid >= 2)
    {
        for (i = 0; i < cycle_num_valid-1; i++)
        {
            for (j = 0; j < cycle_num_valid-1-i; j++)
            {
                if (cycle_list[j] > cycle_list[j+1])
                {
                    tmp = cycle_list[j];
                    cycle_list[j] = cycle_list[j+1];
                    cycle_list[j+1] = tmp;
                }
            }
        }
    }

    /* calculate valid cycle value, shim_chid, slot list and slot cnt */
    for (cc = 0; cc < cycle_num_valid; cc++)
    {
        /* cycle_value */
        p_group_dir->cc[cc].cycle_value = cycle_list[cc];
        /* shim_chid */
        slot_heng = SYS_TMM_FLEXE_GET_SLOT_HENG(cycle_list[cc]);
        (void)_sys_tmm_flexe_slot_heng2shu(lchip, group_node, slot_heng, &slot_shu);
        p_group_dir->cc[cc].shim_chid = p_slot_change->slot[slot_shu].shim_chid_new;
        /* get client node */
        xc_chid = SYS_TMM_FLEXE_CLIENT_SHIM_2_XC_CHID(p_group_dir->cc[cc].shim_chid);
        _sys_tmm_flexe_client_lookup_by_xc_chid(lchip, group_node->flexe_shim_id, xc_chid, &tmp_client_node);
        if (!tmp_client_node)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client use shim_chid %d not exist!\n", p_group_dir->cc[cc].shim_chid);
            ret = CTC_E_NOT_EXIST;
            goto RELEASE_PTR_RETURN;
        }
        /* slot list and slot cnt */
        for (i = 0; i < group_node->inst_cnt; i++)
        {
            slot_cnt = 0;
            for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
            {
                slot = group_node->inst_list[i]*10 + j;
                SYS_CONDITION_CONTINUE(p_slot_change->slot[slot].shim_chid_new != tmp_client_node->shim_chid);
                if ((0 == p_slot_change->slot[slot].change) || (1 == p_slot_change->slot[slot].change)) // 0-fix, 1-add, 2-remove, 3-none
                {
                    p_group_dir->cc[cc].inst[i].slot_list[slot_cnt++] = j;
                }
            }
            p_group_dir->cc[cc].inst[i].slot_cnt = slot_cnt;
        }
    }

    /* calculate cc_subcal_mask */
    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
    {
        tmp_client_node = _ctc_container_of(node, sys_flexe_client_t, head);
        if (tmp_client_node)
        {
            if (group_node->group_id == tmp_client_node->group_id)
            {
                CTC_ERROR_GOTO(_sys_tmm_flexe_client_subcalmask_gen(lchip, group_node, tmp_client_node, dir, p_slot_change), \
                    ret, RELEASE_PTR_RETURN);
            }
        }
    } 

RELEASE_PTR_RETURN:
    if (cycle_list)
    {
        mem_free(cycle_list);
    }

    return ret;
}

STATIC int32
_sys_tmm_flexe_inst_sch_gen(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, uint8 group_inst_offset)
{
    uint8 j = 0, k = 0;
    //uint16 shim_chid = 0;
    uint16 cycle_mask_bmp[SYS_FLEXE_MAX_CYCLE] = {0};
    uint8 slot_bit_num = 0;
    uint8 mask_slot  = 0;
    uint8 cc = 0;  /* client cycle */
    uint8 ic = 0;  /* instance cycle */
    uint8 ic_start = 0;  /* mark the first instance cycle */
    uint8 ic_used[200] = {0};   /* theoretical value range is 0~93 */
    uint8 ic_adv = 0;  /* advance value of instance cycle */
    uint8 ic_adv_max = 0;  /* max advance value of instance cycle */
    uint8 xc_chid = 0;

    sys_flexe_client_t* tmp_client_node = NULL;
    sys_flexe_group_dir_t *p_group_dir = NULL;
    sys_flexe_client_dir_t *p_client_dir = NULL;

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    /* simulate sort and calculate ic_adv_max */
    for (cc = 0; cc < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); cc++)
    {
        if (p_group_dir->cc[cc].inst[group_inst_offset].cc_subcalmask)
        {
            ic = p_group_dir->cc[cc].cycle_value;
        }
        else
        {
            continue;
        }
        while(ic_used[ic])
        {
            ic++;
        }
        /* calculate slot_bit_num */
        slot_bit_num = 0;
        for (j = 0; j < SYS_FLEXE_CLIENT_NUM_BLOCKS; j++)
        {
            if ((p_group_dir->cc[cc].inst[group_inst_offset].cc_subcalmask >> j) & 0x1)
            {
                slot_bit_num++;
            }
        }
        for (k = ic; k < (ic + slot_bit_num); k++)
        {
            if (k >= 200)
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "ERROR: %d exceeds the arrey length when assigning!\n", k);
                return CTC_E_INVALID_PARAM;
            }
            ic_used[k] = 1;
        }
        if ((ic + slot_bit_num) > MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE))
        {
            ic_adv = ic + slot_bit_num - MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE);
        }
        ic_adv_max = (ic_adv > ic_adv_max) ? ic_adv : ic_adv_max;
    }

    /* rx instance schedule sort */
    sal_memset(ic_used, 0, sizeof(ic_used));
    ic = 0;
    for (cc = 0; cc < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); cc++)
    {
        if (p_group_dir->cc[cc].inst[group_inst_offset].cc_subcalmask)
        {
            ic = p_group_dir->cc[cc].cycle_value;
        }
        else
        {
            continue;
        }
        if (ic >= ic_adv_max)
        {
            ic -= ic_adv_max;
        }
        else
        {
            ic = 0;
        }

        while(ic_used[ic])
        {
            ic++;
        }

        ic_start = ic;
        slot_bit_num = 0;
        /* select client cycle in specified instance */
        for (j = 0; j < SYS_FLEXE_CLIENT_NUM_BLOCKS; j++)
        {
            if ((p_group_dir->cc[cc].inst[group_inst_offset].cc_subcalmask >> j) & 0x1)
            {
                slot_bit_num++;
            }
        }

        /* get client info for selected client cycle */
        SYS_CONDITION_CONTINUE(0 == p_group_dir->cc[cc].shim_chid);
        xc_chid = SYS_TMM_FLEXE_CLIENT_SHIM_2_XC_CHID(p_group_dir->cc[cc].shim_chid);
        _sys_tmm_flexe_client_lookup_by_xc_chid(lchip, group_node->flexe_shim_id, xc_chid, &tmp_client_node);
        if (!tmp_client_node)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client use shim_chid %d not exist!\n", p_group_dir->cc[cc].shim_chid);
            return CTC_E_NOT_EXIST;
        }
        p_client_dir = (SYS_FLEXE_DIR_TX == dir) ? &tmp_client_node->tx : &tmp_client_node->rx;

        for (k = 0; k < slot_bit_num; k++)
        {
            mask_slot = p_group_dir->cc[cc].inst[group_inst_offset].slot_list[p_client_dir->read_ptr];
            cycle_mask_bmp[ic] = (1 << mask_slot);

            p_client_dir->read_ptr++;

            if (p_client_dir->read_ptr >= p_group_dir->cc[cc].inst[group_inst_offset].slot_cnt)
            {
                p_client_dir->read_ptr = 0;
            }

            p_group_dir->ic[group_inst_offset][ic].ic_subcalmask = cycle_mask_bmp[ic];
            p_group_dir->ic[group_inst_offset][ic].shim_chid = p_group_dir->cc[cc].shim_chid;

            ic++;
        }
        for (k = ic_start; k < ic; k++)
        {
            ic_used[k] = 1;
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_op_update(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_client_t* client_node, sys_flexe_dir_t dir, sys_flexe_slot_change_t* p_slot_change)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 slot = 0;
    uint8 slot_cnt_old = 0;
    uint8 slot_cnt_new = 0;
    sys_flexe_client_dir_t *p_client_dir = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    p_client_dir = (SYS_FLEXE_DIR_TX == dir) ? &client_node->tx : &client_node->rx;

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            slot = group_node->inst_list[i]*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) + j;
            if (client_node->shim_chid == p_slot_change->slot[slot].shim_chid_old)
            {
                slot_cnt_old++;
            }
            if (client_node->shim_chid == p_slot_change->slot[slot].shim_chid_new)
            {
                slot_cnt_new++;
            }
        }
    }

    if (!slot_cnt_old && slot_cnt_new)
    {
        p_client_dir->op = SYS_FLEXE_CLIENT_ADD;
    }
    else if (slot_cnt_old && !slot_cnt_new)
    {
        p_client_dir->op = SYS_FLEXE_CLIENT_REMOVE;
    }
    else if (!slot_cnt_old && !slot_cnt_new)
    {
        p_client_dir->op = SYS_FLEXE_CLIENT_MAX;
    }
    else
    {
        p_client_dir->op = SYS_FLEXE_CLIENT_RESIZE;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_sch_gen(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 inst_used[SYS_FLEXE_MAX_INST_CNT] = {0};    /* 0:not used, 1:used */

    sys_flexe_group_dir_t *p_group_dir = NULL;
    sys_flexe_slot_change_t slot_change;
    ctc_slistnode_t* node = NULL;
    sys_flexe_client_t* tmp_client_node = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    sal_memset(&slot_change, 0, sizeof(sys_flexe_slot_change_t));

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    /* compare active_slot and inactive_slot */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_slot_change_calc(lchip, group_node, dir, &slot_change));

    /* calculate client op */
    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
    {
        tmp_client_node = _ctc_container_of(node, sys_flexe_client_t, head);
        if (tmp_client_node)
        {
            if (group_node->group_id == tmp_client_node->group_id)
            {
                CTC_ERROR_RETURN(_sys_tmm_flexe_client_op_update(lchip, group_node, tmp_client_node, dir, &slot_change));
            }
        }
    }

    /* clear sch */
    CTC_ERROR_RETURN(_sys_tmm_flexe_init_group_sch_ds(lchip, group_node, dir));

    /* client sch */
    CTC_ERROR_RETURN(_sys_tmm_flexe_client_sch_gen(lchip, group_node, dir, &slot_change));

    /* inst sch */
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            if (SYS_FLEXE_ACTIVE_A == p_group_dir->active)
            {
                if (p_group_dir->dir_inst[i].switch_shim_chid_b[j])
                {
                    inst_used[i] = 1;   //fix,add
                }
                if ((p_group_dir->dir_inst[i].switch_shim_chid_b[j] == 0) && p_group_dir->dir_inst[i].switch_shim_chid_a[j])
                {
                    inst_used[i] = 1;   //remove
                }
            }
            else
            {
                if (p_group_dir->dir_inst[i].switch_shim_chid_a[j])
                {
                    inst_used[i] = 1;   //fix,add
                }
                if ((p_group_dir->dir_inst[i].switch_shim_chid_a[j] == 0) && p_group_dir->dir_inst[i].switch_shim_chid_b[j])
                {
                    inst_used[i] = 1;   //remove
                }
            }
        }
    }

    for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); j++)
    {
        SYS_CONDITION_CONTINUE(0 == inst_used[j]);
        CTC_ERROR_RETURN(_sys_tmm_flexe_inst_sch_gen(lchip, group_node, dir, j));
    }

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_wb_restore_sch(uint8 lchip, void* group_node)
{
    uint8 i = 0;
    uint8 j = 0;
    sys_flexe_group_t* p_group_node = (sys_flexe_group_t*)group_node;

    if (NULL == group_node)
    {
        return CTC_E_INVALID_PTR;
    }

    if (0 == p_group_node->inst_cnt)
    {
        return CTC_E_NONE;
    }

    p_group_node->tx.active = !p_group_node->tx.active;
    p_group_node->rx.active = !p_group_node->rx.active;

    /* clear active slot */
    if (SYS_FLEXE_ACTIVE_A == p_group_node->tx.active)
    { 
        for (i = 0; i < p_group_node->inst_cnt; i++)
        {
            for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
            {
                p_group_node->tx.dir_inst[i].switch_shim_chid_a[j] = 0;
            }
        }
    }
    else
    {
        for (i = 0; i < p_group_node->inst_cnt; i++)
        {
            for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
            {
                p_group_node->tx.dir_inst[i].switch_shim_chid_b[j] = 0;
            }
        }
    }

    if (SYS_FLEXE_ACTIVE_A == p_group_node->rx.active)
    { 
        for (i = 0; i < p_group_node->inst_cnt; i++)
        {
            for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
            {
                p_group_node->rx.dir_inst[i].switch_shim_chid_a[j] = 0;
            }
        }
    }
    else
    {
        for (i = 0; i < p_group_node->inst_cnt; i++)
        {
            for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
            {
                p_group_node->rx.dir_inst[i].switch_shim_chid_b[j] = 0;
            }
        }
    }

    /* sch_gen */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_gen(lchip, p_group_node, SYS_FLEXE_DIR_TX));
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_gen(lchip, p_group_node, SYS_FLEXE_DIR_RX));

    p_group_node->tx.active = !p_group_node->tx.active;
    p_group_node->rx.active = !p_group_node->rx.active;

    /* A/B sync */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_sync(lchip, p_group_node, SYS_FLEXE_DIR_TX));
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_sync(lchip, p_group_node, SYS_FLEXE_DIR_RX));

    return CTC_E_NONE;
}


STATIC int32
_sys_tmm_flexe_shim_cal_gen(uint8 lchip, uint8 flexe_shim_id, sys_flexe_dir_t dir, sys_flexe_client_calcfg_t* flexe_client_cal)
{
    uint8 i                     = 0;
    uint8 index                 = 0;
    uint8 cycle                 = 0;
    uint8 client_num            = 0;
    uint8 fix_client_num        = 0;
    uint8 select_index          = 0;
    uint8 rm_cnt                = 0;
    uint8 cnt                   = 0;
    int32 min_interval          = 0;
    int32 interval_cal          = 0;
    uint32 tmp_xc_chid          = 0;
    uint32 client_list_num      = 0;
    uint32 client_speed_sum     = 0;
    uint32 blank_slot_num       = 0;
    uint32 curr_speed           = 0;

    sys_flexe_client_calcfg_t  *calcfg = NULL;
    sys_flexe_client_t*     client_node[SYS_FLEXE_MAX_CLIENT] = {NULL};
    sys_flexe_client_t*     tmp_client_node = NULL;
    sys_flexe_client_calgen_t* key_list = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    FLEXE_DBG_PRINTF("\nFlexE Shim %d cross calendar!\n", flexe_shim_id);
    FLEXE_DBG_PRINTF("Valid client xc chid are: \n");

    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CLIENT); i++)
    {
        tmp_xc_chid = i;
        _sys_tmm_flexe_client_lookup_by_xc_chid(lchip, flexe_shim_id, tmp_xc_chid, &client_node[i]);
        SYS_CONDITION_CONTINUE(!client_node[i]);
        _sys_tmm_flexe_get_client_speed_val(lchip, client_node[i], dir, SYS_FLEXE_INACTIVE_FLAG, &curr_speed);
        if (!curr_speed)
        {
            FLEXE_DBG_PRINTF("[FlexE] cross chid %d not used yet!\n", tmp_xc_chid);
            continue;
        }

        client_speed_sum += curr_speed;
        client_list_num++;
        FLEXE_DBG_PRINTF("%d(%dG)   ", tmp_xc_chid, curr_speed);
    }
    FLEXE_DBG_PRINTF("\n");
    client_num = client_list_num;
    FLEXE_DBG_PRINTF("--- client_num = %d\n", client_num);

    if (client_speed_sum < 400)
    {
        blank_slot_num = (400-client_speed_sum) / SYS_FLEXE_SLOT_SPEED;
        for (i = 0; i < blank_slot_num; i++)
        {
            client_list_num++;
        }
    }
    FLEXE_DBG_PRINTF("Client list total num(include blank client) is %d\n", client_list_num);
    fix_client_num = client_list_num;
    FLEXE_DBG_PRINTF("--- fix_client_num = %d\n", fix_client_num);

    calcfg = mem_malloc(MEM_DMPS_MODULE, sizeof(sys_flexe_client_calcfg_t) * MCHIP_CAP(SYS_CAP_FLEXE_MAX_CLIENT));
    if(NULL == calcfg)
    {
        return CTC_E_NO_MEMORY;
    }

    FLEXE_DBG_PRINTF("Valid client speed list are: ");
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CLIENT); i++)
    {
        SYS_CONDITION_CONTINUE(!client_node[i]);
        _sys_tmm_flexe_get_client_speed_val(lchip, client_node[i], dir, SYS_FLEXE_INACTIVE_FLAG, &curr_speed);
        if (!curr_speed)
        {
            FLEXE_DBG_PRINTF("[FlexE] cross chid %d not used yet!\n", tmp_xc_chid);
            continue;
        }

        calcfg[cnt].speed = curr_speed;
        calcfg[cnt].xc_chid = client_node[i]->tx_xc_chid;
        FLEXE_DBG_PRINTF("%d(%dG)  ", calcfg[cnt].xc_chid, calcfg[cnt].speed);
        cnt++;
    }
    FLEXE_DBG_PRINTF("\n");

    if (0 == fix_client_num)
    {
        mem_free(calcfg);
        return CTC_E_NONE;
    }
    key_list = mem_malloc(MEM_DMPS_MODULE, sizeof(sys_flexe_client_calgen_t) * fix_client_num);
    if(NULL == key_list)
    {
        mem_free(calcfg);
        return CTC_E_NO_MEMORY;
    }

    sal_memset(key_list, 0, sizeof(sys_flexe_client_calgen_t) * fix_client_num);
    for(index = 0; index < fix_client_num; index++)
    {
        if(index < client_num)
        {
            (key_list + index)->speed =  calcfg[index].speed;
            (key_list + index)->cur_interval =  400 / calcfg[index].speed;
            (key_list + index)->init_interval =  10000 * calcfg[index].speed / 400;
            (key_list + index)->sch_cnt_max = calcfg[index].speed / SYS_FLEXE_SLOT_SPEED;
        }
        else
        {
            (key_list + index)->speed =  SYS_FLEXE_SLOT_SPEED;
            (key_list + index)->cur_interval =  400 / SYS_FLEXE_SLOT_SPEED;
            (key_list + index)->init_interval =  10000 * SYS_FLEXE_SLOT_SPEED / 400;
            (key_list + index)->sch_cnt_max = 1;
        }
    }

    for(cycle = 0; cycle < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); cycle ++)
    {
        /*2. select client, it's cur_interval is minimum*/
        min_interval = MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE);
        select_index = 0;

        for(index = 0; index < fix_client_num; index++)
        {
            if(0 == (key_list + index)->rm_flag)
            {
                if((key_list + index)->cur_interval < min_interval)
                {
                    min_interval = (key_list + index)->cur_interval;
                    select_index = index;

                    FLEXE_DBG_PRINTF("\n\ncycle = %d, cur_interval = %d, min_interval = %d, ", cycle, (key_list + index)->cur_interval, min_interval);
                    FLEXE_DBG_PRINTF("select_index = %d\n", select_index);
                }
            }
        }

        FLEXE_DBG_PRINTF("%-3x  ", (select_index < client_num ? select_index : 0xff));

        flexe_client_cal[cycle].xc_chid = (select_index < client_num ? calcfg[select_index].xc_chid : SYS_FLEXE_UNUSED_FLAG_U8);
        FLEXE_DBG_PRINTF("g_flexe_client_cal[%d][%d].xc_chid = %d\n", flexe_shim_id, cycle, flexe_client_cal[cycle].xc_chid);
        flexe_client_cal[cycle].rx_xc_chid = flexe_client_cal[cycle].xc_chid;
        FLEXE_DBG_PRINTF("%-3x  ", flexe_client_cal[cycle].xc_chid);
        if(0 == ((cycle + 1) % 8))
        {
            FLEXE_DBG_PRINTF("\n");
        }

        /*3. update database*/
        (key_list + select_index)->sel = 0;
        (key_list + select_index)->pending = 1;
        (key_list + select_index)->sch_sel_cnt ++;
        (key_list + select_index)->sch_cnt ++;
        (key_list + select_index)->cur_interval = 400 / (key_list + select_index)->speed;
        (key_list + select_index)->rm_flag = 1;
        rm_cnt ++;

        for(index = 0; index < fix_client_num; index++)
        {
            (key_list + index)->sch_total_cnt ++;
            (key_list + index)->cur_interval --;

            if(((key_list + index)->sch_cnt) == ((key_list + index)->sch_cnt_max))
            {
                (key_list + index)->sel = 0;
                (key_list + index)->pending = 0;
            }
        }

        /*4. Reload Client*/
        for(index = 0; index < fix_client_num; index++)
        {
            if(1 == (key_list + index)->rm_flag)
            {
                interval_cal = (key_list + index)->pending ? (10000 * (key_list + index)->sch_sel_cnt / (key_list + index)->sch_total_cnt):0;

                if(((key_list + index)->pending == 1) && (interval_cal <= (key_list + index)->init_interval) && (0 == (key_list + index)->sel))
                {
                    (key_list + index)->sel = 1;
                    (key_list + index)->rm_flag = 0;
                    rm_cnt --;
                }
            }
        }

        if(rm_cnt == fix_client_num)
        {
            for(index = 0; index < fix_client_num; index++)
            {
                if((key_list + index)->pending == 1)
                {
                    (key_list + index)->sel = 1;
                    (key_list + index)->rm_flag = 0;
                    rm_cnt --;
                }
            }
        }
    }
    FLEXE_DBG_PRINTF("\n\n");

    for (cycle = 0; cycle < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); cycle++)
    {
        if (SYS_FLEXE_UNUSED_FLAG_U8 == flexe_client_cal[cycle].xc_chid)
        {
            flexe_client_cal[cycle].flow_type = SYS_FLEXE_FLOW_MAX;
            flexe_client_cal[cycle].rx_xc_chid = SYS_FLEXE_UNUSED_FLAG_U8;
            flexe_client_cal[cycle].speed = 0;
            flexe_client_cal[cycle].mac_id = SYS_FLEXE_UNUSED_FLAG_U16;
        }
        else
        {
            tmp_xc_chid = flexe_client_cal[cycle].xc_chid;
            _sys_tmm_flexe_client_lookup_by_xc_chid(lchip, flexe_shim_id, tmp_xc_chid, &tmp_client_node);
            flexe_client_cal[cycle].flow_type = \
                (SYS_FLEXE_FLOW_MAX == tmp_client_node->flow_type) ? SYS_FLEXE_FLOW_TYPE_B : tmp_client_node->flow_type;
            flexe_client_cal[cycle].rx_xc_chid = tmp_client_node->rx_xc_chid;
            _sys_tmm_flexe_get_client_speed_val(lchip, tmp_client_node, dir, SYS_FLEXE_INACTIVE_FLAG, &curr_speed);
            flexe_client_cal[cycle].speed = curr_speed;
            flexe_client_cal[cycle].mac_id = tmp_client_node->mac_id;
        }
    }

    if (calcfg)
    {
        mem_free(calcfg);
    }
    if (key_list)
    {
        mem_free(key_list);
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_port_speed_update(uint8 lchip, sys_flexe_client_t* client_node, uint8 enable)
{
    uint32 tx_speed = 0;
    sys_datapath_lport_attr_t*  port_attr = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    port_attr = sys_usw_datapath_get_port_capability(lchip, CTC_MAP_GPORT_TO_LPORT(client_node->gport));
    if (!port_attr)
    {
        return CTC_E_NONE;
    }

    /* calc current speed */
    _sys_tmm_flexe_get_client_speed_val(lchip, client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_INACTIVE_FLAG, &tx_speed);

    port_attr->speed_value = tx_speed; /* update for show port mac-link(get speed) */

    if (enable)
    {
        SYS_FLEXE_SPEED_VAL_TO_MODE(tx_speed, port_attr->speed_mode);
    }
    else
    {
        port_attr->speed_mode = CTC_PORT_SPEED_MAX;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_set_datapath(uint8 lchip, sys_flexe_client_t* client_node, uint8 enable)
{
    sys_tmm_ds_target_attr_t    ds_attr;
    sys_usw_port_mac_config_t port_mac_config = {0};
    sys_datapath_lport_attr_t*  port_attr = NULL;
    sys_flexe_group_t *group_node = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, client %d set datapath %s\n", __FUNCTION__, __LINE__, \
        client_node->client_id, enable?"Enable":"Disable");

    _sys_tmm_flexe_group_lookup(lchip, client_node->group_id, &group_node);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group ID %d not exist!\n", client_node->group_id);
        return CTC_E_NOT_EXIST;
    }

    port_attr = sys_usw_datapath_get_port_capability(lchip, CTC_MAP_GPORT_TO_LPORT(client_node->gport));
    if (!port_attr)
    {
        return CTC_E_NONE;
    }

    /* fill ds_attr info */
    sal_memset(&ds_attr, 0, sizeof(sys_tmm_ds_target_attr_t));
    ds_attr.lport_num = 1;
    ds_attr.lport_list[0].lport = CTC_MAP_GPORT_TO_LPORT(client_node->gport);
    ds_attr.lport_list[0].chan_id = port_attr->chan_id;
    ds_attr.lport_list[0].upt_flag = SYS_DS_LPORT_REMAIN;
    ds_attr.lport_list[0].serdes_relate_num = 0;

    CTC_ERROR_RETURN(_sys_tmm_dynamic_switch_q_flush(lchip, &ds_attr));
    CTC_ERROR_RETURN(sys_usw_add_port_to_channel(lchip, CTC_MAP_GPORT_TO_LPORT(client_node->gport), MCHIP_CAP(SYS_CAP_CHANID_DROP), 0));

    CTC_ERROR_RETURN(_sys_tmm_dynamic_switch_datapath(lchip, &ds_attr));

    if (enable && (SYS_FLEXE_CLIENT_REMOVE != client_node->tx.op)) 
    {
        CTC_ERROR_RETURN(sys_usw_queue_set_port_drop_en(lchip, client_node->gport, FALSE, &ds_attr.shp_profile[0]));
        sys_usw_add_port_to_channel(lchip, CTC_MAP_GPORT_TO_LPORT(client_node->gport), port_attr->chan_id, 0);
    }

    if ((SYS_FLEXE_CLIENT_ADD == client_node->tx.op) || (SYS_FLEXE_CLIENT_RESIZE == client_node->tx.op))
    {
        port_mac_config.lport = CTC_MAP_GPORT_TO_LPORT(client_node->gport);
        port_mac_config.speed_mode = port_attr->speed_mode;
        port_mac_config.speed_value = port_attr->speed_value;
        port_mac_config.interface_type = port_attr->interface_type;
        CTC_ERROR_RETURN(sys_usw_port_mac_config_attach(lchip, &port_mac_config));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_set_datapath_main(uint8 lchip, sys_flexe_client_t* client_node, uint8 enable)
{
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, client %d , %s, set datapath %s\n", __FUNCTION__, __LINE__, \
        client_node->client_id, (2 == client_node->aps_role)?"protect":"main", enable?"Enable":"Disable");

    if (2 == client_node->aps_role)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_set_datapath(lchip, client_node, enable));
    }
    else
    {
        /* update port speed */
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_port_speed_update(lchip, client_node, enable));
        /* set datapath */
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_set_datapath(lchip, client_node, enable));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_set_datapath(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint8 enable = 0;
    uint32 active_speed     = 0;
    uint32 inactive_speed   = 0;
    ctc_slistnode_t* node = NULL;
    sys_flexe_client_t* tmp_client_node = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
    {
        tmp_client_node = _ctc_container_of(node, sys_flexe_client_t, head);
        SYS_CONDITION_CONTINUE(!tmp_client_node);
        SYS_CONDITION_CONTINUE(group_node->group_id != tmp_client_node->group_id);
        _sys_tmm_flexe_get_client_speed_val(lchip, tmp_client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_ACTIVE_FLAG,   &active_speed);
        _sys_tmm_flexe_get_client_speed_val(lchip, tmp_client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_INACTIVE_FLAG, &inactive_speed);
        SYS_CONDITION_CONTINUE(active_speed == inactive_speed);
        enable = inactive_speed ? 1 : 0; 
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_set_datapath_main(lchip, tmp_client_node, enable));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_update_cross(uint8 lchip, 
                                                sys_flexe_group_t* group_node, 
                                                sys_flexe_client_t* client_node, 
                                                sys_flexe_dir_t dir, 
                                                sys_flexe_client_calcfg_t* flexe_client_cal)
{
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s(%s)\n", __FUNCTION__, (SYS_FLEXE_DIR_TX == dir)?"TX":"RX");

    if (SYS_FLEXE_UNUSED_FLAG_U16 == client_node->mac_id)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] Client %d haven't binded MAC, won't set mac/cross\n", \
            client_node->client_id);
        return CTC_E_NONE;
    }

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] Client %d set mac/cross %s\n", client_node->client_id, (SYS_FLEXE_DIR_TX == dir)?"TX":"RX");
    CTC_ERROR_RETURN(_sys_tmm_flexe_client_mac_config(lchip, client_node, dir));
    CTC_ERROR_RETURN(_sys_tmm_flexe_client_cross_config(lchip, client_node, dir, flexe_client_cal));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_update_mac_cross(uint8 lchip, sys_flexe_group_t *group_node, sys_flexe_dir_t dir)
{
    uint32 active_speed     = 0;
    uint32 inactive_speed   = 0;

    ctc_slistnode_t* node = NULL;
    sys_flexe_client_t* tmp_client_node = NULL;
    sys_flexe_client_calcfg_t flexe_client_cal[SYS_FLEXE_MAX_CYCLE];

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /* cfg datapath and cross */
    CTC_ERROR_RETURN(_sys_tmm_flexe_shim_cal_gen(lchip, group_node->flexe_shim_id, dir, flexe_client_cal));
    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
    {
        tmp_client_node = _ctc_container_of(node, sys_flexe_client_t, head);
        SYS_CONDITION_CONTINUE(!tmp_client_node);
        SYS_CONDITION_CONTINUE(group_node->group_id != tmp_client_node->group_id);
        _sys_tmm_flexe_get_client_speed_val(lchip, tmp_client_node, dir, SYS_FLEXE_ACTIVE_FLAG,   &active_speed);
        _sys_tmm_flexe_get_client_speed_val(lchip, tmp_client_node, dir, SYS_FLEXE_INACTIVE_FLAG, &inactive_speed);
        SYS_CONDITION_CONTINUE(active_speed == inactive_speed);
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_update_cross(lchip, group_node, tmp_client_node, dir, flexe_client_cal));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_cfg_slot_tx2rx(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 xc_chid = 0;
    uint8 slot_shu = 0;
    uint8 slot_heng = 0;
    uint8 phy_slot = 0;
    uint8 physical_serdes_id = 0;
    sys_flexe_phy_t*   tmp_phy_node   = NULL;
    sys_flexe_client_t* tx_client_node = NULL;
    sys_flexe_client_t* rx_client_node = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            if ((group_node->rx.dir_inst[i].slot_cfg_shim_chid[j]) && \
                (group_node->tx.dir_inst[i].slot_cfg_shim_chid[j]) && \
                (group_node->rx.dir_inst[i].slot_cfg_shim_chid[j] != group_node->tx.dir_inst[i].slot_cfg_shim_chid[j]))
            {
                /* tx phy node */
                tmp_phy_node = _sys_tmm_flexe_phy_lookup_by_inst(lchip, group_node->flexe_shim_id, group_node->inst_list[i]);
                if (!tmp_phy_node)
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group_node %d fail to copy slot tx to rx!\n", group_node->group_id);
                    return CTC_E_INVALID_PARAM;
                }
                CTC_ERROR_RETURN(_sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, tmp_phy_node->logical_serdes_base, &physical_serdes_id));
                /* tx phy slot */
                slot_shu = MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) * group_node->inst_list[i] + j;
                (void)_sys_tmm_flexe_slot_shu2heng(lchip, group_node, slot_shu, &slot_heng);
                phy_slot = slot_heng - MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) * tmp_phy_node->inst_base;
                /* tx client node */
                xc_chid = SYS_TMM_FLEXE_CLIENT_SHIM_2_XC_CHID(group_node->tx.dir_inst[i].slot_cfg_shim_chid[j]);
                _sys_tmm_flexe_client_lookup_by_xc_chid(lchip, group_node->flexe_shim_id, xc_chid, &tx_client_node);
                /* rx client node */
                xc_chid = SYS_TMM_FLEXE_CLIENT_SHIM_2_XC_CHID(group_node->rx.dir_inst[i].slot_cfg_shim_chid[j]);
                _sys_tmm_flexe_client_lookup_by_xc_chid(lchip, group_node->flexe_shim_id, xc_chid, &rx_client_node);
                /* return error */
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] [TX->RX] Failed to bind phy %d slot %d to client %d, which is working in client %d\n", \
                    physical_serdes_id, phy_slot, tx_client_node->client_id, rx_client_node->client_id);
                return CTC_E_INVALID_PARAM;
            }
        }
    }

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            group_node->rx.dir_inst[i].slot_cfg_shim_chid[j] = group_node->tx.dir_inst[i].slot_cfg_shim_chid[j];
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_cfg_slot_clear(uint8 lchip, sys_flexe_group_t* group_node,           sys_flexe_client_t* client_node, sys_flexe_dir_t dir)
{
    uint8 i = 0;
    uint8 j = 0;
    sys_flexe_group_dir_t *p_group_dir = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            if (client_node->shim_chid == p_group_dir->dir_inst[i].slot_cfg_shim_chid[j])
            {
                p_group_dir->dir_inst[i].slot_cfg_shim_chid[j] = 0;
            }
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_inactive_slot_clear(uint8 lchip, sys_flexe_group_t* group_node,            sys_flexe_client_t* client_node, sys_flexe_dir_t dir)
{
    uint8 i = 0;
    uint8 j = 0;

    sys_flexe_group_dir_t *p_group_dir = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            if (SYS_FLEXE_ACTIVE_A == p_group_dir->active)
            {
                if (client_node->shim_chid == p_group_dir->dir_inst[i].switch_shim_chid_b[j])
                {
                    p_group_dir->dir_inst[i].switch_shim_chid_b[j] = 0;
                }
            }
            else
            {
                if (client_node->shim_chid == p_group_dir->dir_inst[i].switch_shim_chid_a[j])
                {
                    p_group_dir->dir_inst[i].switch_shim_chid_a[j] = 0;
                }
            }
        }
    }

    return CTC_E_NONE;
}

/* read RX frame 0 of asic instance overhead */
STATIC int32
_sys_tmm_flexe_get_inst_crcac(uint8 lchip, uint32 flexe_shim_id, uint8 asic_inst, uint8 dir, uint8 type, uint32* p_val32)
{
    uint32 c0 = 0;
    uint32 c1 = 0;
    uint32 c2 = 0;
    int32 ret = CTC_E_NONE;

    if (FLEXE_OH_FIELD_TYPE_CR == type)
    {
        _sys_tmm_flexe_read_ohram_per_fld(lchip, flexe_shim_id, 0, asic_inst, FLEXE_OH_FIELD_CR, p_val32, dir);
    }
    else if (FLEXE_OH_FIELD_TYPE_CA == type)
    {
        _sys_tmm_flexe_read_ohram_per_fld(lchip, flexe_shim_id, 0, asic_inst, FLEXE_OH_FIELD_CA, p_val32, dir);
    }
    else if (FLEXE_OH_FIELD_TYPE_C_BIT == type)
    {
        _sys_tmm_flexe_read_ohram_per_fld(lchip, flexe_shim_id, 0, asic_inst, FLEXE_OH_FIELD_C_0, &c0, dir);
        _sys_tmm_flexe_read_ohram_per_fld(lchip, flexe_shim_id, 0, asic_inst, FLEXE_OH_FIELD_C_1, &c1, dir);
        _sys_tmm_flexe_read_ohram_per_fld(lchip, flexe_shim_id, 0, asic_inst, FLEXE_OH_FIELD_C_2, &c2, dir);
        if (c0 + c1 + c2 <= 1) /* 1 '1' at most */
        {
            *p_val32 = 0;
        }
        else  /* 2 '1's at least */
        {
            *p_val32 = 1;
        }
    }
    else
    {
        ret = CTC_E_INVALID_PARAM;
    }

    return ret;
}

STATIC int32
_sys_tmm_flexe_get_inst_tx_caval(uint8 lchip, uint8 flexe_shim_id, uint8 inst_id, uint32 *p_val)
{
    uint32          cmd       = 0;
    uint32          index     = 0;
    uint32          val32     = 0;
    SocFlexeCfg_m   soc_rst;

    cmd = DRV_IOR(SocFlexeCfg_t, DRV_ENTRY_FLAG);
    index = DRV_INS(flexe_shim_id, 0);
    DRV_IOCTL(lchip, index, cmd, &soc_rst);

    DRV_IOR_FIELD(lchip, SocFlexeCfg_t, SocFlexeCfg_cfgTxManualCaValue_f, &val32, &soc_rst);

    *p_val = (val32 >> inst_id) & 0x1;

    return CTC_E_NONE;
}

/*
  Description: get cr/ca/c in oh, require phys in group are all up
 */
STATIC int32
_sys_tmm_flexe_get_group_crcac(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, sys_flexe_oh_field_type_t type, uint32* p_crcac)
{
    uint8 lock      = 0;
    uint8 mflock    = 0;
    uint32 crcac    = 0;
    uint32 read_cnt = 0;

    SYS_CONDITION_RETURN(!p_crcac, CTC_E_NONE);

    while (1)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_ohlock(lchip, group_node, &lock));
        CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_ohmflock(lchip, group_node, &mflock));
        read_cnt++;

        if ((lock && mflock) || (read_cnt >= 7))
        {
            break;
        }

        /* sleep 1ms after a round*/
        sal_task_sleep(1);
    }

    CTC_ERROR_RETURN(_sys_tmm_flexe_get_inst_crcac(lchip, group_node->flexe_shim_id, group_node->inst_list[0], dir, type, &crcac));

    *p_crcac = crcac;

    return CTC_E_NONE;
}

/*
  Description: get cr/ca/c in oh, data is from the first lock instance
  Scene: phys in group are not all up 
 */
STATIC int32
_sys_tmm_flexe_get_group_crcac_raw(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, sys_flexe_oh_field_type_t type, uint32* p_crcac)
{
    uint8 i         = 0;
    uint8 ohlock    = 0;
    uint8 ohmflock  = 0;
    uint8 asic_inst = 0;
    uint32 crcac    = 0;

    SYS_CONDITION_RETURN(!p_crcac, CTC_E_NONE);

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        asic_inst = group_node->inst_list[i];

        CTC_ERROR_RETURN(_sys_tmm_flexe_get_inst_ohlock(lchip, group_node->flexe_shim_id, asic_inst, &ohlock));
        CTC_ERROR_RETURN(_sys_tmm_flexe_get_inst_ohmflock(lchip, group_node->flexe_shim_id, asic_inst, &ohmflock));
        if (ohlock && ohmflock)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_get_inst_crcac(lchip, group_node->flexe_shim_id, asic_inst, dir, type, &crcac));
            break;
        }
        else
        {
            if ((group_node->inst_cnt - 1) == i)
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "%% [FlexE] no phy in group id %d is up!\n", group_node->group_id);
                return CTC_E_NOT_READY;
            }
        }
    }

    *p_crcac = crcac;

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_group_all_crcac(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_dir_t dir, sys_flexe_oh_field_type_t type, uint32* p_crcac)
{
    uint8 i             = 0;
    uint8 asic_inst     = 0;
    uint8 phy_speed     = 0;
    int32 all_crcac     = -1;
    uint32 tmp_crcac    = 0;

    SYS_CONDITION_RETURN(!p_crcac, CTC_E_NONE);

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &phy_speed);

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        asic_inst = group_node->inst_list[i];
        if ((FLEXE_OH_FIELD_TYPE_CA == type) && (SYS_FLEXE_DIR_TX == dir))
        {
            _sys_tmm_flexe_get_inst_tx_caval(lchip, group_node->flexe_shim_id, asic_inst, &tmp_crcac);
        }
        else
        {
            SYS_CONDITION_CONTINUE((SYS_FLEXE_DIR_TX == dir) && (CTC_PORT_SPEED_50G != phy_speed) && (asic_inst%2));
            _sys_tmm_flexe_get_inst_crcac(lchip, group_node->flexe_shim_id, asic_inst, dir, type, &tmp_crcac);
        }
        
        if (all_crcac == -1)
        {
            all_crcac = tmp_crcac;
        }
        if (tmp_crcac != all_crcac)
        {
            all_crcac = -1;
            break;
        }
    }

    if (-1 == all_crcac)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "%% [FlexE] group id %d, dir %s, type %d, read oh crcac not ready!\n", \
            group_node->group_id, dir?"TX":"RX", type);
        return CTC_E_NOT_READY;
    }

    *p_crcac = all_crcac;

    return CTC_E_NONE;
}

/*
  Description: get client cal in oh
  Input parameter: act_flag : in dynamic negotiation, judge by local rx table
                              in other case, judge by remote tx table
                   check_match : 0: require phys in group are all up
                                 1: do not require phys in group are all up
 */
STATIC int32
_sys_tmm_flexe_client_rx_slot_calc(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_client_t* client_node, uint8 act_flag, uint8 check_match, ctc_flexe_client_slot_t* p_client_slot)
{
    uint8 i                     = 0;
    uint8 j                     = 0;
    uint8 asic_inst             = 0;
    uint8 speed_mode            = 0;
    uint8 physical_serdes_id    = 0;
    uint8 phy_cnt               = 0;
    uint8 phy_inst_cnt          = 0;
    uint8 phy_inst_index        = 0;
    uint8 slot_per_phy          = 0;
    uint8 ohlock                = 0;
    uint8 ohmflock              = 0;
    uint32 client_number        = 0;
    uint32 rx_table             = 0;
    uint32 c                    = 0;
    int32 ret                   = CTC_E_NONE;

    sys_flexe_phy_t *p_phy = NULL;
    sys_flexe_ohram_info_t* p_ohram_info_rx = NULL;

    /* only support active or inactive flag */
    if (SYS_FLEXE_CFG_FLAG == act_flag)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] Unsupported act_flag\n");
        return CTC_E_INVALID_PARAM;
    }

    /* read rx ohram */
    if (check_match)
    {
        ret = _sys_tmm_flexe_get_group_crcac_raw(lchip, group_node, SYS_FLEXE_DIR_RX, FLEXE_OH_FIELD_TYPE_C_BIT, &c);
    }
    else
    {
        ret = _sys_tmm_flexe_get_group_crcac(lchip, group_node, SYS_FLEXE_DIR_RX, FLEXE_OH_FIELD_TYPE_C_BIT, &c);
    }
    if (ret)
    {
        return CTC_E_NONE;
    }

    /* in dynamic negotiation, use rx_hw_table */
    if (SYS_FLEXE_INACTIVE_FLAG == act_flag)
    {
        ret = _sys_tmm_flexe_get_group_manual_table(lchip, group_node, SYS_FLEXE_DIR_RX, &rx_table);
        if (0 != ret) 
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group %d client %d rx_slot_calc fail because of get table!\n", group_node->group_id, client_node->client_id);
            return CTC_E_NONE;
        }
        c = rx_table;
    }

    /* alloc memory */
    p_ohram_info_rx = (sys_flexe_ohram_info_t*)mem_malloc(MEM_DMPS_MODULE, sizeof(sys_flexe_ohram_info_t));
    if(NULL == p_ohram_info_rx)
    {
        return CTC_E_NO_MEMORY;
    }

    sal_memset(p_ohram_info_rx, 0, sizeof(sys_flexe_ohram_info_t));

    /* read oh and fill p_client_slot */
    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);
    phy_inst_cnt = SYS_TMM_FLEXE_PHY_2_INST_CNT(speed_mode);

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        asic_inst = group_node->inst_list[i];

        if (check_match)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_get_inst_ohlock(lchip, group_node->flexe_shim_id, asic_inst, &ohlock));
            CTC_ERROR_RETURN(_sys_tmm_flexe_get_inst_ohmflock(lchip, group_node->flexe_shim_id, asic_inst, &ohmflock));
            SYS_CONDITION_CONTINUE(!ohlock || !ohmflock);
        }

        /* inst index in a phy */
        phy_inst_index = i % phy_inst_cnt;
        /* when inst is the first in a phy, calculate serdes_id */
        if (0 == phy_inst_index)
        {
            /* get physical serdes id */
            p_phy = _sys_tmm_flexe_phy_lookup_by_inst(lchip, group_node->flexe_shim_id, asic_inst);
            if (!p_phy)
            {
                ret = CTC_E_INVALID_PARAM;
                goto RELEASE_PTR_RETURN;
            }
            CTC_ERROR_GOTO(_sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, p_phy->logical_serdes_base, &physical_serdes_id), \
                ret, RELEASE_PTR_RETURN);
            if (SYS_TMM_USELESS_ID8 == physical_serdes_id)
            {
                ret = CTC_E_INVALID_PARAM;
                goto RELEASE_PTR_RETURN;
            }
            /* fill p_slot serdes_id */
            p_client_slot->slot[phy_cnt].serdes_id = physical_serdes_id;
        }
        /* read every inst in 50G phy, read even inst in other phy */
        SYS_CONDITION_CONTINUE((CTC_PORT_SPEED_50G != speed_mode) && asic_inst%2);
        /* read rx ohram */
        sal_memset(p_ohram_info_rx, 0, sizeof(sys_flexe_ohram_info_t));
        CTC_ERROR_GOTO(_sys_tmm_flexe_parse_ohram(lchip, group_node, asic_inst, p_ohram_info_rx, SYS_FLEXE_DIR_RX), \
            ret, RELEASE_PTR_RETURN);
        /* fill slot */
        for (j = 0; j < SYS_FLEXE_OH_MAX_SLOT_PER_INST; j++)
        {
            if (SYS_FLEXE_ACTIVE_FLAG == act_flag)
            {
                client_number = (0 == c) ? p_ohram_info_rx->inst_client_map[asic_inst][j] : p_ohram_info_rx->inst_client_map_b[asic_inst][j];
            }
            else
            {
                client_number = (1 == c) ? p_ohram_info_rx->inst_client_map[asic_inst][j] : p_ohram_info_rx->inst_client_map_b[asic_inst][j];
            }
            SYS_CONDITION_CONTINUE(0 == client_number);
            SYS_CONDITION_CONTINUE(client_number != client_node->client_number);

            /* fill p_slot slot_bmp */
            slot_per_phy = phy_inst_index / 2 * SYS_FLEXE_OH_MAX_SLOT_PER_INST + j;
            CTC_BMP_SET(p_client_slot->slot[phy_cnt].slot_bmp, slot_per_phy);
        }
        /* when inst is the last in a phy, phy_cnt++ */
        if ((((phy_inst_cnt - 2) == phy_inst_index) && (CTC_PORT_SPEED_50G != speed_mode)) || (CTC_PORT_SPEED_50G == speed_mode))
        {
            phy_cnt++;
        }
    }

    p_client_slot->phy_cnt = phy_cnt;

RELEASE_PTR_RETURN:
    if (p_ohram_info_rx) 
    {
        mem_free(p_ohram_info_rx);
    }

    return ret;
}

STATIC int32
_sys_tmm_flexe_group_update_mac(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint8  tx_have_slot   = FALSE;
    uint8  rx_have_slot   = FALSE;
    uint8  rx_active_slot   = FALSE;
    ctc_slistnode_t* node = NULL;
    sys_flexe_client_t* tmp_client_node = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
    {
        tmp_client_node = _ctc_container_of(node, sys_flexe_client_t, head);
        SYS_CONDITION_CONTINUE(!tmp_client_node);
        SYS_CONDITION_CONTINUE(group_node->group_id != tmp_client_node->group_id);
        if (SYS_FLEXE_UNUSED_FLAG_U16 != tmp_client_node->mac_id)
        {
            _sys_tmm_flexe_get_client_slot_cnt(lchip, tmp_client_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_ACTIVE_FLAG, &rx_active_slot);
            if (rx_active_slot)
            {
                CTC_ERROR_RETURN(_sys_tmm_mac_set_tx_force_fault_by_mac_id(lchip, tmp_client_node->mac_id, 0));
            }
            else
            {
                CTC_ERROR_RETURN(_sys_tmm_mac_set_tx_force_fault_by_mac_id(lchip, tmp_client_node->mac_id, CTC_PORT_FAULT_FORCE));
            }
            _sys_tmm_flexe_check_client_slot(lchip, tmp_client_node, SYS_FLEXE_DIR_TX, &tx_have_slot);
            _sys_tmm_flexe_check_client_slot(lchip, tmp_client_node, SYS_FLEXE_DIR_RX, &rx_have_slot);
            if (!tx_have_slot && !rx_have_slot)
            {
                CTC_ERROR_RETURN(_sys_tmm_flexe_client_free_mac(lchip, tmp_client_node));
            }
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_fill_rx_slot(uint8 lchip, sys_flexe_group_t* group_node, uint8 act_flag)
{
    ctc_slistnode_t* node = NULL;
    sys_flexe_client_t* tmp_client_node = NULL;
    ctc_flexe_client_slot_t client_slot;
    ctc_flexe_slot_bmp_t slot_phy[8];

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
    {
        sal_memset(&client_slot, 0, sizeof(ctc_flexe_client_slot_t));
        sal_memset(slot_phy, 0, 8 * sizeof(ctc_flexe_slot_bmp_t));
        client_slot.slot = slot_phy;

        tmp_client_node = _ctc_container_of(node, sys_flexe_client_t, head);
        SYS_CONDITION_CONTINUE(!tmp_client_node);
        SYS_CONDITION_CONTINUE(group_node->group_id != tmp_client_node->group_id);

        /* calculate client slot */
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_rx_slot_calc(lchip, group_node, tmp_client_node, act_flag, FALSE, &client_slot));

        /* rx client bind slot */
        CTC_ERROR_RETURN(_sys_flexe_client_txrx_bind_slot(lchip, tmp_client_node, SYS_FLEXE_DIR_RX, &client_slot));
    }

    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
    {
        sal_memset(&client_slot, 0, sizeof(ctc_flexe_client_slot_t));
        sal_memset(slot_phy, 0, 8 * sizeof(ctc_flexe_slot_bmp_t));
        client_slot.slot = slot_phy;

        tmp_client_node = _ctc_container_of(node, sys_flexe_client_t, head);
        SYS_CONDITION_CONTINUE(!tmp_client_node);
        SYS_CONDITION_CONTINUE(group_node->group_id != tmp_client_node->group_id);

        /* calculate client slot */
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_rx_slot_calc(lchip, group_node, tmp_client_node, act_flag, FALSE, &client_slot));

        /* rx client bind slot */
        CTC_ERROR_RETURN(_sys_flexe_client_txrx_bind_slot(lchip, tmp_client_node, SYS_FLEXE_DIR_RX, &client_slot));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_group_update_inactive_slot(uint8 lchip, sys_flexe_group_t* group_node, uint8 enable)
{
    if (enable)
    {
        /* from cfg_slot to inactive switch_slot */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_slot_cfg2switch(lchip, group_node, SYS_FLEXE_DIR_TX));
    }
    else
    {
        /* from active switch_slot to inactive switch_slot */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_switch_slot_sync(lchip, group_node, SYS_FLEXE_DIR_TX));
    }

    CTC_ERROR_RETURN(_sys_tmm_flexe_group_send_client_cal(lchip, group_node, SYS_FLEXE_INACTIVE_FLAG));

    return CTC_E_NONE;    
}

int32
sys_tmm_flexe_phy_link_up_event(uint8 lchip, uint16 lport, sys_datapath_lport_attr_t* port_attr)
{
    uint8 i                     = 0;
    uint8 inst_id               = 0;
    uint8 oh_lock               = 0;
    uint8 ohmf_lock             = 0;
    uint8 loop_cnt              = 0;
    uint8 logical_serdes_id     = 0;
    uint8 pcs_link              = 0;
    sys_flexe_group_t *group_node = NULL;
    sys_flexe_phy_t* phy_node     = NULL;

    /* check phy link up */
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_phy_status_by_lport(lchip, lport, port_attr, SYS_FLEXE_PCS_LINK, &pcs_link));
    if (!pcs_link)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Please run port %d port-en enable after port is link up!\n", lport);
        return CTC_E_INVALID_CONFIG;
    }

    /* check group exist */
    logical_serdes_id = SYS_TMM_MAP_SERDES_TO_HSS_IDX(port_attr->multi_serdes_id[0]) * 8 + port_attr->pcs_idx;
    group_node = _sys_tmm_flexe_group_lookup_by_serdes(lchip, logical_serdes_id);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] port %d is not used by any group\n", lport);
        return CTC_E_INVALID_CONFIG;
    }

    /* check phy exist */
    phy_node = (sys_flexe_phy_t *)_sys_tmm_flexe_get_phy_node(lchip, logical_serdes_id);
    if (!phy_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] port %d is not used by any phy\n", lport);
        return CTC_E_INVALID_CONFIG;
    }

    /* check ohlock/ohmflock */
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_phy_status_by_lport(lchip, lport, port_attr, SYS_FLEXE_OH_LOCK, &oh_lock));
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_phy_status_by_lport(lchip, lport, port_attr, SYS_FLEXE_OHMF_LOCK, &ohmf_lock));
    while (!oh_lock || !ohmf_lock)
    {
        sal_task_sleep(5);
        if((loop_cnt++) > 10)
        {
            /* Timeout */
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] instance OH/OHMF LockLos, please do port-en again after OH/OHMF Lock!\n");
            return CTC_E_INVALID_CONFIG;
        }
        oh_lock = 0;
        ohmf_lock = 0;
        CTC_ERROR_RETURN(_sys_tmm_flexe_get_phy_status_by_lport(lchip, lport, port_attr, SYS_FLEXE_OH_LOCK, &oh_lock));
        CTC_ERROR_RETURN(_sys_tmm_flexe_get_phy_status_by_lport(lchip, lport, port_attr, SYS_FLEXE_OHMF_LOCK, &ohmf_lock));
    }

    FLEXE_DUMP("\n\n\n*************************************************************************\n");
    FLEXE_DUMP("port %d port-en enable\n", lport);
    FLEXE_DUMP("\n*************************************************************************\n\n");

    /*1. unmask ohlock/rpf */
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_phy_ohlock_intr_mask(lchip, logical_serdes_id, FALSE));
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_phy_rpf_intr_mask(lchip, logical_serdes_id, FALSE));

    /*2. clear group's instance ohlock,crcerr_cnt */
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        inst_id = group_node->inst_list[i];
        CTC_ERROR_RETURN(_sys_tmm_flexe_clear_inst_ohlock(lchip, group_node->flexe_shim_id, inst_id));
        CTC_ERROR_RETURN(_sys_tmm_flexe_clear_inst_crcerr_cnt(lchip, group_node->flexe_shim_id, inst_id));
    }

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_phy_link_down_event(uint8 lchip, uint16 lport, sys_datapath_lport_attr_t* port_attr)
{
    uint8  logical_serdes_id    = 0;
    sys_flexe_group_t *group_node = NULL;

    logical_serdes_id = SYS_TMM_MAP_SERDES_TO_HSS_IDX(port_attr->multi_serdes_id[0]) * 8 + port_attr->pcs_idx;
    group_node = _sys_tmm_flexe_group_lookup_by_serdes(lchip, logical_serdes_id);
    if (!group_node)
    {
        return CTC_E_NONE;
    }

    FLEXE_DUMP("\n\n\n*************************************************************************\n");
    FLEXE_DUMP("port %d port-en disable\n", lport);
    FLEXE_DUMP("\n*************************************************************************\n\n");

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_phy_number(uint8 lchip, uint16 serdes_id, uint32 phy_number)
{
    uint8 phy_speed           = 0;
    uint8 logical_serdes_id   = 0;
    uint8 logical_serdes_base = 0;
    uint8 phy_lane_num        = 0;
    uint32 phy_number_max     = 0;
    sys_datapath_serdes_info_t* p_serdes  = NULL;
    sys_flexe_group_t *group_node = NULL;

    /* calculate phy lane num of phy */
    _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)serdes_id, &logical_serdes_id);
    SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
    CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, logical_serdes_id, &p_serdes));

    group_node = _sys_tmm_flexe_group_lookup_by_serdes(lchip, logical_serdes_id);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] PHY %d not binded to any group, CANNOT set phy number \n", serdes_id);
        return CTC_E_INVALID_CONFIG;
    }

    SYS_FLEXE_MODE_2_SPEED(p_serdes->mode, phy_speed);
    phy_number_max = SYS_FLEXE_MAX_PHY_NUM(phy_speed);
    if (phy_number > phy_number_max)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] phy number %u out of range [1-%d]\n", phy_number, phy_number_max);
        return CTC_E_INVALID_PARAM;
    }

    _sys_tmm_flexe_get_phy_lane_num(lchip, logical_serdes_id, &phy_lane_num);
    SYS_CONDITION_RETURN(!phy_lane_num, CTC_E_INVALID_PARAM);
    logical_serdes_base = logical_serdes_id / phy_lane_num * phy_lane_num;

    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_phy_number_same(lchip, group_node, logical_serdes_base, phy_number));
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_phy_number_sequence(lchip, group_node, logical_serdes_base, phy_number));
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_group_phy_number(lchip, group_node, logical_serdes_base, phy_number));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_client_slot(uint8 lchip, sys_flexe_client_t* client_node, void* p_value)
{
    uint8 i                     = 0;
    uint8 j                     = 0;
    uint8 flag                  = 0;
    uint8 slot                  = 0;
    uint8 slot_heng             = 0;
    uint8 phy_cnt               = 0;  /* cnt of phy in the group */
    uint8 phy_cnt_valid         = 0;  /* cnt of phy which has the client's slot */
    uint8 speed_mode            = 0;
    uint8 slot_per_phy          = 0;
    uint8 phy_inst_cnt          = 0;
    uint8 group_inst_offset     = 0;
    uint8 physical_serdes_id    = 0;
    sys_flexe_group_t* group_node = NULL;
    ctc_flexe_client_slot_t* p_flexe_slot = NULL;

    p_flexe_slot = (ctc_flexe_client_slot_t*)p_value;
    p_flexe_slot->phy_cnt = 0;
    sal_memset(p_flexe_slot->slot, 0, TMM_GROUP_MAX_PHY_CNT * sizeof(ctc_flexe_slot_bmp_t));

    _sys_tmm_flexe_group_lookup(lchip, client_node->group_id, &group_node);
    if (!group_node)
    {
        return CTC_E_NONE;
    }

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);
    phy_inst_cnt = SYS_TMM_FLEXE_PHY_2_INST_CNT(speed_mode);

    for (phy_cnt = 0; phy_cnt < group_node->phy_cnt; phy_cnt++)
    {
        CTC_ERROR_RETURN(_sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, group_node->phy_list[phy_cnt].logical_serdes_base, &physical_serdes_id));
        p_flexe_slot->slot[phy_cnt_valid].serdes_id = physical_serdes_id;
        for (i = group_node->phy_list[phy_cnt].inst_base; i < (group_node->phy_list[phy_cnt].inst_base + phy_inst_cnt); i++)
        {
            _sys_tmm_flexe_get_group_inst_offset_by_asic_inst(lchip, group_node, i, &group_inst_offset);
            for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
            {
                if ((group_node->tx.dir_inst[group_inst_offset].slot_cfg_shim_chid[j]) == client_node->shim_chid)
                {
                    slot = group_node->inst_list[group_inst_offset]*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) + j; 
                    (void)_sys_tmm_flexe_slot_shu2heng(lchip, group_node, slot, &slot_heng);
                    /* fill p_slot slot_bmp */
                    slot_per_phy = slot_heng - group_node->phy_list[phy_cnt].inst_base*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST);
                    CTC_BMP_SET(p_flexe_slot->slot[phy_cnt_valid].slot_bmp, slot_per_phy);
                    flag = 1;
                }
            }
        }
        if (flag)
        {
            phy_cnt_valid++;
            flag = 0;
        } 
    }

    p_flexe_slot->phy_cnt = phy_cnt_valid;

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_phy_timeslot(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_phy_t* phy_node, void* p_value)
{
    uint8 i                     = 0;
    uint8 j                     = 0;
    uint8 slot                  = 0;
    uint8 slot_heng             = 0;
    uint8 slot_num              = 0;
    uint8 serdes_slot           = 0;
    uint8 physical_serdes_id    = 0;
    uint8 speed_mode            = 0;
    uint8 phy_inst_cnt          = 0;

    sys_flexe_client_t* tmp_client_node = NULL;
    ctc_slistnode_t* node = NULL;
    ctc_flexe_phy_timeslot_t* p_flexe_timeslot = NULL;

    p_flexe_timeslot = (ctc_flexe_phy_timeslot_t*)p_value;
    sal_memset(p_flexe_timeslot->client_id, 0, CTC_FLEXE_INSTANCE_SLOT_NUM * sizeof(uint32));

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);
    phy_inst_cnt = SYS_TMM_FLEXE_PHY_2_INST_CNT(speed_mode);

    /* physical serdes id */
    CTC_ERROR_RETURN(_sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, phy_node->logical_serdes_base, &physical_serdes_id));
    p_flexe_timeslot->serdes_id = physical_serdes_id;
    /* find every client in the group */
    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
    {
        tmp_client_node = _ctc_container_of(node, sys_flexe_client_t, head);
        SYS_CONDITION_CONTINUE(!tmp_client_node);
        SYS_CONDITION_CONTINUE(group_node->group_id != tmp_client_node->group_id);
        for (i = phy_node->inst_base; i < (phy_node->inst_base+phy_inst_cnt); i++)
        {
            for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
            {
                if (SYS_FLEXE_ACTIVE_A == group_node->tx.active)
                {
                    SYS_CONDITION_CONTINUE(tmp_client_node->shim_chid != group_node->tx.dir_inst[i].switch_shim_chid_a[j]);
                }
                else
                {
                    SYS_CONDITION_CONTINUE(tmp_client_node->shim_chid != group_node->tx.dir_inst[i].switch_shim_chid_b[j]);
                }
                slot = group_node->inst_list[i]*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) + j;
                (void)_sys_tmm_flexe_slot_shu2heng(lchip, group_node, slot, &slot_heng);
                serdes_slot = slot_heng - phy_node->inst_base*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST);
                p_flexe_timeslot->client_id[serdes_slot] = tmp_client_node->client_id;
                slot_num++;
            }
        }
    }
    p_flexe_timeslot->slot_num = slot_num;

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_get_phy_ohram_info(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_phy_t* phy_node, void* p_value)
{
    uint8 i                 = 0;
    uint8 slot_num          = 0;
    uint8 link_stat         = 0;
    uint8 asic_inst         = 0;
    uint8 inst_valid        = 0;
    uint8 speed_mode        = 0;
    uint32 frame_num        = 0;
    int32 ret               = CTC_E_NONE;
    sys_flexe_ohram_info_t* p_ohram_info = NULL;
    ctc_flexe_phy_oh_t* p_phy_ohram = NULL;

    p_phy_ohram = (ctc_flexe_phy_oh_t*)p_value;
    sal_memset(p_phy_ohram->flexe_map, 0, CTC_FLEXE_OH_MF_NUM * sizeof(uint8));
    sal_memset(p_phy_ohram->client_bmp_a, 0, CTC_FLEXE_INSTANCE_SLOT_NUM * sizeof(uint16));
    sal_memset(p_phy_ohram->client_bmp_b, 0, CTC_FLEXE_INSTANCE_SLOT_NUM * sizeof(uint16));

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);
    if (CTC_PORT_SPEED_50G != speed_mode)
    {
        frame_num = SYS_FLEXE_OH_FRAME_NUM;
        slot_num = SYS_FLEXE_OH_MAX_SLOT_PER_INST;
    }
    else
    {
        frame_num = SYS_FLEXE_OH_FRAME_NUM_50G;
        slot_num = MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST);
    }

    /* check input instance offset */
    switch (speed_mode)
    {
        case CTC_PORT_SPEED_50G:
        case CTC_PORT_SPEED_100G:
            if (0 == p_phy_ohram->instance_offset)
            {
                inst_valid = 1;
            }
            break;
        case CTC_PORT_SPEED_200G:
            if (0 == p_phy_ohram->instance_offset || 1 == p_phy_ohram->instance_offset)
            {
                inst_valid = 1;
            }
            break;
        case CTC_PORT_SPEED_400G:
            if (0 == p_phy_ohram->instance_offset || 1 == p_phy_ohram->instance_offset || 2 == p_phy_ohram->instance_offset || 3 == p_phy_ohram->instance_offset)
            {
                inst_valid = 1;
            }
            break;
        default:
            break;
    }
    if (!inst_valid)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] phy %d instance offset %d is not exist!\n", phy_node->logical_serdes_base, p_phy_ohram->instance_offset);
        return CTC_E_INVALID_PARAM;
    }

    /* check whether phy in the group is all up */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_phy_up(lchip, group_node, &link_stat));
    if (!link_stat)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] phy in group %d is not all up, CANNOT read ohram!\n", group_node->group_id);
        return CTC_E_INVALID_PARAM;
    }

    /* request memory space */
    p_ohram_info = (sys_flexe_ohram_info_t*)mem_malloc(MEM_DMPS_MODULE, sizeof(sys_flexe_ohram_info_t));
    if(NULL == p_ohram_info)
    {
        goto DONE;
    }

    sal_memset(p_ohram_info, 0, sizeof(sys_flexe_ohram_info_t));
    /* calculate asic instance */
    asic_inst = phy_node->inst_base + 2 * p_phy_ohram->instance_offset;
    /* read ohram */
    ret = _sys_tmm_flexe_parse_ohram(lchip, group_node, asic_inst, p_ohram_info, p_phy_ohram->dir);
    if (ret != 0)
    {
        ret = CTC_E_NONE;
        goto DONE;
    }
    p_phy_ohram->group_num  = p_ohram_info->group_num;
    p_phy_ohram->instance_num  = p_ohram_info->inst_num;
    for (i = 0; i < frame_num; i++)
    {
        p_phy_ohram->flexe_map[i] = p_ohram_info->flexe_map[i];
    }
    for (i = 0; i < slot_num; i++)
    {
        p_phy_ohram->client_bmp_a[i] = p_ohram_info->inst_client_map[asic_inst][i];
        p_phy_ohram->client_bmp_b[i] = p_ohram_info->inst_client_map_b[asic_inst][i];
    }

DONE:
    if (p_ohram_info) mem_free(p_ohram_info);

    return ret;
}

STATIC int32
_sys_tmm_flexe_set_phy_rpf_val(uint8 lchip, uint32 flexe_shim_id, sys_flexe_phy_t* phy_node, uint8 rpf_val)
{
    if (CTC_CHIP_SERDES_LG_MODE == phy_node->pcs_mode || CTC_CHIP_SERDES_LG_R1_MODE == phy_node->pcs_mode)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_inst_rpf_val(lchip, flexe_shim_id, phy_node->inst_base, rpf_val));
    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_inst_rpf_val(lchip, flexe_shim_id, phy_node->inst_base, rpf_val));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_inst_rpf_val(lchip, flexe_shim_id, (phy_node->inst_base+1), rpf_val));
    }

    return CTC_E_NONE;
}

void
_sys_tmm_flexe_fill_event(uint8 lchip, uint8 flexe_shim_id, uint8 asic_inst, ctc_flexe_status_event_t* flexe_event)
{
    uint8  i   = 0;
    uint8  tmp_serdes = 0;
    uint8  phy_link_stat = 0;
    ctc_flexe_event_type_t type = 0;
    sys_flexe_group_t* group_node = NULL;
    sys_flexe_phy_t* phy_node = NULL;
    sys_flexe_ohram_info_t* ohram_info = NULL;

    ohram_info = (sys_flexe_ohram_info_t*)mem_malloc(MEM_DMPS_MODULE, sizeof(sys_flexe_ohram_info_t));
    if(NULL == ohram_info)
    {
        return;
    }
    sal_memset(ohram_info, 0, sizeof(sys_flexe_ohram_info_t));

    for (i = 0; i < CTC_FLEXE_OH_MF_NUM; i++)
    {
        flexe_event->flexe_map[i] = 0;
    }

    group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, flexe_shim_id, asic_inst);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] DP %d Inst %d not included in any flexe group, return!\n", flexe_shim_id, asic_inst);
        mem_free(ohram_info);
        return;
    }

    (void)_sys_tmm_flexe_check_group_phy_up(lchip, group_node, &phy_link_stat);
    if (!phy_link_stat)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] DP %d Inst %d phy not link up, return!\n", flexe_shim_id, asic_inst);
        mem_free(ohram_info);
        return;
    }

    FLEXE_DBG_PRINTF("##### _sys_tmm_flexe_fill_event,  dp = %d\n", flexe_shim_id);

    type = flexe_event->event_type;

    phy_node = _sys_tmm_flexe_phy_lookup_by_inst(lchip, group_node->flexe_shim_id, asic_inst);
    if (!phy_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] DP %d Inst %d not included in any flexe group, return!\n", flexe_shim_id, asic_inst);
        mem_free(ohram_info);
        return;
    }
    _sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, phy_node->logical_serdes_base, &tmp_serdes);
    flexe_event->serdes_id = tmp_serdes;
    FLEXE_DBG_PRINTF("FlexE Event: phy_id:%d\n", flexe_event->serdes_id);

    if ((CTC_FLEXE_EVENT_RPF != type)
        && (CTC_FLEXE_EVENT_LOF != type)
        && (CTC_FLEXE_EVENT_LOMF != type)
        && (CTC_FLEXE_EVENT_CRC_ERR != type)
        && (CTC_FLEXE_EVENT_PHY_DESKEW_OVER != type))
    {
        (void)_sys_tmm_flexe_parse_ohram(lchip, group_node, asic_inst, ohram_info, SYS_FLEXE_DIR_RX);
        for (i = 0; i < CTC_FLEXE_OH_MF_NUM; i++)
        {
            flexe_event->flexe_map[i] = ohram_info->flexe_map[i];
        }

        flexe_event->group_num    = ohram_info->group_num;
        flexe_event->instance_num = ohram_info->inst_num;

        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] FlexE Event: event_type: %d, group_num:%d, instance_num:%d\n",
            flexe_event->event_type, flexe_event->group_num, flexe_event->instance_num);
    }
    mem_free(ohram_info);
}

#define ____FLEXE_STATIC_SWITCH____

STATIC int32
_sys_tmm_flexe_set_rx_sw_table_from_hw(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint32 hw_table     = 0;

    /* disable rx_spare */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_set_rx_spare(lchip, group_node, FALSE));

    /* get hw_table */
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_manual_table(lchip, group_node, SYS_FLEXE_DIR_RX, &hw_table));

    /* get hw_table */
    if (hw_table != group_node->rx.active)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_rx_c_handle(lchip, group_node));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_force_clear_switch(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_client_t* client_node, sys_flexe_dir_t dir)
{
    uint8 curr_active = 0;

    /* modify switch_sel */
    if (SYS_FLEXE_DIR_TX == dir)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, dir, group_node->tx.active));
    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, dir, group_node->rx.active));
    }

    /* enable switch_en */
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_en(lchip, group_node, dir, TRUE));

    /* wait until switch ok */
    if (SYS_FLEXE_DIR_TX == dir)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, dir, group_node->tx.active));
    }    
    else
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, dir, group_node->rx.active));
    }

#if 1
    /* calculate sch */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_gen(lchip, group_node, dir));

    /* sch config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_config(lchip, group_node, dir));

    /* flush */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_gen(lchip, group_node, dir));

    /* flush config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config(lchip, group_node, dir));

    /* set client datapath which bind port */
    if (SYS_FLEXE_DIR_TX == dir)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_set_datapath(lchip, group_node));
    }

    /* set mac and FlexE cross */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_mac_cross(lchip, group_node, dir));

    /* switch table */
    curr_active = (SYS_FLEXE_DIR_TX == dir) ? group_node->tx.active : group_node->rx.active;
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, dir, !curr_active));

    /* wait until switch ok */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, dir, !curr_active));

    /* update group flag */
    if (SYS_FLEXE_DIR_TX == dir)
    {
        group_node->tx.active = !curr_active;
    }
    else
    {
        group_node->rx.active = !curr_active;
    }

    /* A/B sync */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_sync(lchip, group_node, dir));

    /* if A->A or B->B, swith again */
    /* flush */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_gen(lchip, group_node, dir));

    /* flush config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config(lchip, group_node, dir));

    /* switch */
    curr_active = (SYS_FLEXE_DIR_TX == dir) ? group_node->tx.active : group_node->rx.active;
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, dir, !curr_active));

    /* wait until switch ok */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, dir, !curr_active));

    /* update group flag */
    if (SYS_FLEXE_DIR_TX == dir)
    {
        group_node->tx.active = !curr_active;
    }
    else
    {
        group_node->rx.active = !curr_active;
    }
#endif

    /* clear cfg slot */
    CTC_ERROR_RETURN(_sys_tmm_flexe_client_cfg_slot_clear(lchip, group_node, client_node, dir));

    /* copy cfg_slot to switch_slot */
    CTC_ERROR_RETURN(_sys_tmm_flexe_client_inactive_slot_clear(lchip, group_node, client_node, dir));

    /* write client cal */
    if (SYS_FLEXE_DIR_TX == dir)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_static_send_client_cal(lchip, group_node));
    }

    /* sch */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_gen(lchip, group_node, dir));

    /* sch config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_config(lchip, group_node, dir));

    /* flush */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_gen(lchip, group_node, dir));

    /* flush config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config(lchip, group_node, dir));

    /* set client datapath which bind port */
    if (SYS_FLEXE_DIR_TX == dir)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_set_datapath(lchip, group_node));
    }

    /* set mac and FlexE cross */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_mac_cross(lchip, group_node, dir));

    /* switch table */
    curr_active = (SYS_FLEXE_DIR_TX == dir) ? group_node->tx.active : group_node->rx.active;
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, dir, !curr_active));

    /* wait until switch ok */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, dir, !curr_active));

    /* update group flag */
    if (SYS_FLEXE_DIR_TX == dir)
    {
        group_node->tx.active = !curr_active;
    }
    else
    {
        group_node->rx.active = !curr_active;
    }

    /* A/B sync */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_sync(lchip, group_node, dir));

    /* flush */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_gen(lchip, group_node, dir));

    /* flush config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config(lchip, group_node, dir));

    /* switch again */
    curr_active = (SYS_FLEXE_DIR_TX == dir) ? group_node->tx.active : group_node->rx.active;
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, dir, !curr_active));

    /* wait until switch ok */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, dir, !curr_active));

    /* update group flag */
    if (SYS_FLEXE_DIR_TX == dir)
    {
        group_node->tx.active = !curr_active;
    }
    else
    {
        group_node->rx.active = !curr_active;
    }

    /* update mac */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_mac(lchip, group_node));

    /* disable switch_en */
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_en(lchip, group_node, dir, FALSE));

    return CTC_E_NONE;    
}

STATIC int32
_sys_tmm_flexe_client_force_clear(uint8 lchip, sys_flexe_client_t* client_node, sys_flexe_dir_t dir)
{
    uint8 ohlock        = TRUE;  /*TRUE-lock  FALSE-loss*/
    uint8 mac_tx_en     = 0;
    uint8 mac_rx_en     = 0;
    sys_flexe_group_t* group_node = NULL;

    _sys_tmm_flexe_group_lookup(lchip, client_node->group_id, &group_node);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group ID %d not exists!\n", client_node->group_id);
        return CTC_E_ENTRY_NOT_EXIST;
    }

    /* check group switch_mode */
    if (SYS_FLEXE_STATIC_SWITCH == group_node->switch_mode)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group %d switch-mode is %d, please use static switch to remove slot!\n", \
            group_node->group_id, group_node->switch_mode);
        return CTC_E_INVALID_CONFIG;
    }

    /* check chip version */
    if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION == SYS_CHIP_SUB_VERSION_A))
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] current chip version not support force clear slot!\n");
        return CTC_E_INVALID_PARAM;
    }

    /* check if mac disable */
    if (SYS_FLEXE_UNUSED_FLAG_U16 != client_node->mac_id)
    {
        CTC_ERROR_RETURN(_sys_tmm_mac_get_flexe_mac_en(lchip, client_node->mac_id, SYS_FLEXE_DIR_TX, &mac_tx_en));
        CTC_ERROR_RETURN(_sys_tmm_mac_get_flexe_mac_en(lchip, client_node->mac_id, SYS_FLEXE_DIR_RX, &mac_rx_en));
        if (mac_tx_en || mac_rx_en)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client %d must mac disable when empty slot!\n", client_node->client_id);
            return CTC_E_INVALID_PARAM;
        }
    }
    else
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "%% [FlexE] client %d is already empty, return!\n", client_node->client_id);
        return CTC_E_NONE;
    }
    
    /* check whether phy in the group is all ohlock */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_ohlock(lchip, group_node, &ohlock));
    if (!ohlock)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group %d phy not all ohlock, not support force clear slot!\n", client_node->group_id);
        return CTC_E_INVALID_PARAM;
    }

    /* if sw_table != hw_table, do rx_c_handle */
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_rx_sw_table_from_hw(lchip, group_node));

    /* clear active slot */
    CTC_ERROR_RETURN(_sys_tmm_flexe_client_force_clear_switch(lchip, group_node, client_node, dir));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_client_force_recover_switch(uint8 lchip, sys_flexe_group_t* group_node, sys_flexe_client_t* client_node)
{
    uint8 curr_active = 0;

    /* modify switch_sel */
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, SYS_FLEXE_DIR_RX, group_node->rx.active));

    /* enable switch_en */
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_en(lchip, group_node, SYS_FLEXE_DIR_RX, TRUE));

    /* wait until switch ok */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_RX, group_node->rx.active));

#if 1
    /* calculate sch */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_gen(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* RX sch config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_config(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* RX flush */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_gen(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* RX flush config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* set mac and FlexE cross */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_mac_cross(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* switch table */
    curr_active = group_node->rx.active;
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, SYS_FLEXE_DIR_RX, !curr_active));

    /* wait until rx switch ok */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_RX, !curr_active));

    /* update group RX flag */
    group_node->rx.active = (SYS_FLEXE_ACTIVE_A == curr_active) ? SYS_FLEXE_ACTIVE_B : SYS_FLEXE_ACTIVE_A;

    /* A/B sync */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_sync(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* if A->A or B->B, swith again */
    /* RX flush */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_gen(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* RX flush config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* switch rx */
    curr_active = group_node->rx.active;
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, SYS_FLEXE_DIR_RX, !curr_active));

    /* wait until rx switch ok */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_RX, !curr_active));

    /* update group rx flag */
    group_node->rx.active = (SYS_FLEXE_ACTIVE_A == curr_active) ? SYS_FLEXE_ACTIVE_B : SYS_FLEXE_ACTIVE_A;
#endif

    /* every client in the group bind slot from oh */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_fill_rx_slot(lchip, group_node, SYS_FLEXE_ACTIVE_FLAG));

    /* modify switch_sel and enable switch_en again */
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, SYS_FLEXE_DIR_RX, group_node->rx.active));
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_en(lchip, group_node, SYS_FLEXE_DIR_RX, TRUE));

    /* wait until switch ok */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_RX, group_node->rx.active));

    /* cpy cfg_slot to switch_slot */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_slot_cfg2switch(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* sch */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_gen(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* sch config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_config(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* flush */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_gen(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* flush config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* set mac and FlexE cross */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_mac_cross(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* switch table */
    curr_active = group_node->rx.active;
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, SYS_FLEXE_DIR_RX, !curr_active));

    /* wait until switch ok */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_RX, !curr_active));

    /* update group flag */
    group_node->rx.active = !curr_active;

    /* A/B sync */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_sync(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* flush */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_gen(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* flush config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* switch again */
    curr_active = group_node->rx.active;
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, SYS_FLEXE_DIR_RX, !curr_active));

    /* wait until switch ok */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_RX, !curr_active));

    /* update group flag */
    group_node->rx.active = !curr_active;

    /* update mac */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_mac(lchip, group_node));

    /* disable switch_en */
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_en(lchip, group_node, SYS_FLEXE_DIR_RX, FALSE));

    return CTC_E_NONE;    
}

STATIC int32
_sys_tmm_flexe_client_force_recover(uint8 lchip, sys_flexe_client_t* client_node)
{
    uint8 alarm         = 0;
    uint8 ohlock        = TRUE;  /*TRUE-lock  FALSE-loss*/
    sys_flexe_group_t* group_node = NULL;

    _sys_tmm_flexe_group_lookup(lchip, client_node->group_id, &group_node);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group ID %d not exists!\n", client_node->group_id);
        return CTC_E_ENTRY_EXIST;
    }

    /* check group switch_mode */
    if (SYS_FLEXE_STATIC_SWITCH == group_node->switch_mode)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group %d switch-mode is %d, please use static switch to set slot!\n", \
            group_node->group_id, group_node->switch_mode);
        return CTC_E_INVALID_CONFIG;
    }

    /* check chip version */
    if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION == SYS_CHIP_SUB_VERSION_A))
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] current chip version not support force set slot!\n");
        return CTC_E_INVALID_PARAM;
    }

    /* check whether phy in the group is all ohlock */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_ohlock(lchip, group_node, &ohlock));
    if (!ohlock)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group %d phy not all ohlock, not support force set slot!\n", client_node->group_id);
        return CTC_E_INVALID_PARAM;
    }

    /* check group number, phy number, flexe map mismatch */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_check_ohram_alarm(lchip, group_node));
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_ohram_alarm(lchip, group_node, &alarm));
    if (alarm)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group %d alarm, not support force set slot!\n", group_node->group_id);
    }

    /* if sw_table != hw_table, do rx_c_handle */
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_rx_sw_table_from_hw(lchip, group_node));

    /* set rx active slot from oh */
    CTC_ERROR_RETURN(_sys_tmm_flexe_client_force_recover_switch(lchip, group_node, client_node));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_static_switch_manual(uint8 lchip, sys_flexe_group_t* group_node, uint32 val)
{
    uint8 switch_same   = 0;
    uint8 ohlock        = 0;
    uint8 lb_ohlock     = 0;
    uint8 curr_active   = 0;
    ctc_flexe_status_event_t flexe_event;

    /* check whether phy in the group is all ohlock */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_ohlock(lchip, group_node, &ohlock));

    /* group PHY loopback when phy is not all ohlock */
    if (!ohlock)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_phy_link_intr_mask(lchip, group_node, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_phy_static_cfg(lchip, group_node, TRUE, TRUE));
        /* check whether phy in the group is all up */
        CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_ohlock(lchip, group_node, &lb_ohlock));
        if (!lb_ohlock)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] phy in group %d is not all ohlock, CANNOT run static switch!\n", group_node->group_id);
            return CTC_E_INVALID_PARAM;
        }
    }

    /************************* TX START ************************/
    /* current and dest are the same or not */
    switch_same = (val == group_node->tx.active) ? 1 : 0;

    /* copy tx cfg_slot to switch_slot */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_slot_cfg2switch(lchip, group_node, SYS_FLEXE_DIR_TX));

    /* write client cal */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_static_send_client_cal(lchip, group_node));

    /* TX sch */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_gen(lchip, group_node, SYS_FLEXE_DIR_TX));

    /* TX sch config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_config(lchip, group_node, SYS_FLEXE_DIR_TX));

    /* TX flush */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_gen(lchip, group_node, SYS_FLEXE_DIR_TX));

    /* TX flush config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config(lchip, group_node, SYS_FLEXE_DIR_TX));

    /* set client datapath which bind port */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_set_datapath(lchip, group_node));

    /* set mac and FlexE cross */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_mac_cross(lchip, group_node, SYS_FLEXE_DIR_TX));

    /* switch table */
    curr_active = group_node->tx.active;
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, SYS_FLEXE_DIR_TX, !curr_active));

    /* wait until tx switch ok */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_TX, !curr_active));

    /* update group TX flag */
    group_node->tx.active = (SYS_FLEXE_ACTIVE_A == curr_active) ? SYS_FLEXE_ACTIVE_B : SYS_FLEXE_ACTIVE_A;

    /* A/B sync */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_sync(lchip, group_node, SYS_FLEXE_DIR_TX));

    /* if A->A or B->B, swith again */
    if (1 == switch_same)
    {
        /* TX flush */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_gen(lchip, group_node, SYS_FLEXE_DIR_TX));

        /* TX flush config */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config(lchip, group_node, SYS_FLEXE_DIR_TX));

        /* switch tx */
        curr_active = group_node->tx.active;
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, SYS_FLEXE_DIR_TX, !curr_active));

        /* wait until tx switch ok */
        CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_TX, !curr_active));

        /* update group TX flag */
        group_node->tx.active = (SYS_FLEXE_ACTIVE_A == curr_active) ? SYS_FLEXE_ACTIVE_B : SYS_FLEXE_ACTIVE_A;
    }

    /* tx system interrupt callback */
    flexe_event.flag = 0;
    flexe_event.event_type = CTC_FLEXE_EVENT_TX_SWITCH_OK;
    flexe_event.group_num = group_node->group_number;
    _sys_tmm_flexe_intr_cb(lchip, &flexe_event);
    /************************* TX END ************************/

    /************************* RX START************************/
    /* current and dest are the same or not */
    switch_same = (val == group_node->rx.active) ? 1 : 0;

    /* copy tx cfg slot to rx */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_cfg_slot_tx2rx(lchip, group_node));

    /* cpy cfg_slot to switch_slot */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_slot_cfg2switch(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* calculate sch */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_gen(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* RX sch config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_config(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* RX flush */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_gen(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* RX flush config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* set mac and FlexE cross */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_mac_cross(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* ignore fault to prevent link down */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_ignore_local_fault(lchip, group_node, TRUE));

    /* switch table */
    curr_active = group_node->rx.active;
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, SYS_FLEXE_DIR_RX, !curr_active));

    /* wait until rx switch ok */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_RX, !curr_active));

    /* update group RX flag */
    group_node->rx.active = (SYS_FLEXE_ACTIVE_A == curr_active) ? SYS_FLEXE_ACTIVE_B : SYS_FLEXE_ACTIVE_A;

    /* A/B sync */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_sync(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* if A->A or B->B, swith again */
    if (1 == switch_same)
    {
        /* RX flush */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_gen(lchip, group_node, SYS_FLEXE_DIR_RX));

        /* RX flush config */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config(lchip, group_node, SYS_FLEXE_DIR_RX));

        /* switch rx */
        curr_active = group_node->rx.active;
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, SYS_FLEXE_DIR_RX, !curr_active));

        /* wait until rx switch ok */
        CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_RX, !curr_active));

        /* update group rx flag */
        group_node->rx.active = (SYS_FLEXE_ACTIVE_A == curr_active) ? SYS_FLEXE_ACTIVE_B : SYS_FLEXE_ACTIVE_A;
    }

    /* rx system interrupt callback */
    flexe_event.flag = 0;
    flexe_event.event_type = CTC_FLEXE_EVENT_RX_SWITCH_OK;
    flexe_event.group_num = group_node->group_number;
    _sys_tmm_flexe_intr_cb(lchip, &flexe_event);

    /* rehandle fault */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_ignore_local_fault(lchip, group_node, FALSE));
    /************************* RX END ************************/

    /* update mac */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_mac(lchip, group_node));

    /* group PHY loopback clear when phy is not all ohlock */
    if (FALSE == ohlock)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_phy_static_cfg(lchip, group_node, TRUE, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_phy_link_intr_mask(lchip, group_node, FALSE));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_static_switch_lb(uint8 lchip, sys_flexe_group_t* group_node, uint32 val, uint8 is_normal)
{
    uint8 i             = 0;
    uint8 loop_num      = 0;
    uint8 inst_bmp      = 0;
    uint8 curr_active   = 0;
    uint8 ohlock        = 0;
    uint32 crcac        = 0;
    ctc_flexe_status_event_t flexe_event;

    /* current and dest are the same */
    loop_num = (val == group_node->tx.active) ? 2 : 1;

    for (i = 0; i < group_node->inst_cnt; i++)
    {
        inst_bmp |= (1 << group_node->inst_list[i]);
    }

    /************************* group PHY loopback ************************/
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_phy_link_intr_mask(lchip, group_node, TRUE));
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_phy_static_cfg(lchip, group_node, is_normal, TRUE));

    /* check whether phy in the group is all up */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_ohlock(lchip, group_node, &ohlock));
    if (!ohlock)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] phy in group %d is not all ohlock, CANNOT run static switch!\n", group_node->group_id);
        return CTC_E_INVALID_PARAM;
    }

    for (i = 0; i < loop_num; i++)
    {
        curr_active = group_node->tx.active;

        /************************* Prepare TX START ************************/
        /* copy tx cfg_slot to switch_slot */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_slot_cfg2switch(lchip, group_node, SYS_FLEXE_DIR_TX));

        /* write client cal */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_static_send_client_cal(lchip, group_node));

        /* TX sch */
        CTC_ERROR_RETURN(_sys_tmm_flexe_sch_gen(lchip, group_node, SYS_FLEXE_DIR_TX));

        /* TX sch config */
        CTC_ERROR_RETURN(_sys_tmm_flexe_sch_config(lchip, group_node, SYS_FLEXE_DIR_TX));

        /* TX flush */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_gen(lchip, group_node, SYS_FLEXE_DIR_TX));

        /* TX flush config */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config(lchip, group_node, SYS_FLEXE_DIR_TX));
        /************************* Prepare TX END ************************/

        /************************* Prepare RX START ************************/
        /* copy tx cfg slot to rx */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_cfg_slot_tx2rx(lchip, group_node));

        /* cpy cfg_slot to switch_slot */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_slot_cfg2switch(lchip, group_node, SYS_FLEXE_DIR_RX));

        /* calculate sch */
        CTC_ERROR_RETURN(_sys_tmm_flexe_sch_gen(lchip, group_node, SYS_FLEXE_DIR_RX));

        /* RX sch config */
        CTC_ERROR_RETURN(_sys_tmm_flexe_sch_config(lchip, group_node, SYS_FLEXE_DIR_RX));

        /* RX flush */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_gen(lchip, group_node, SYS_FLEXE_DIR_RX));

        /* RX flush config */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config(lchip, group_node, SYS_FLEXE_DIR_RX));
        /************************* Prepare RX END ************************/

        /************************* TX START ************************/
        /* enable rx_spare */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_set_rx_spare(lchip, group_node, TRUE));

        /* set client datapath which bind port */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_set_datapath(lchip, group_node));

        /* set mac and FlexE cross */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_mac_cross(lchip, group_node, SYS_FLEXE_DIR_TX));

        /* Send cr/ca/c */
        crcac = curr_active ? 0 : 1;
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_send_ca(lchip, group_node, crcac));
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_oh(lchip, group_node, FLEXE_OH_FIELD_TYPE_CR, (void *)&crcac));
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_oh(lchip, group_node, FLEXE_OH_FIELD_TYPE_C_BIT, (void *)&crcac));

        /* wait until tx switch ok */
        if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A))
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_TX, !curr_active));
        }
        else
        {
            sal_task_sleep(10);
        }

        /* update group TX flag */
        group_node->tx.active = (SYS_FLEXE_ACTIVE_A == curr_active) ? SYS_FLEXE_ACTIVE_B : SYS_FLEXE_ACTIVE_A;

        /* A/B sync */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_sync(lchip, group_node, SYS_FLEXE_DIR_TX));
        /************************* TX END ************************/

        /************************* RX START************************/
        /* disable rx_spare */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_set_rx_spare(lchip, group_node, FALSE));

        /* set mac and FlexE cross */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_mac_cross(lchip, group_node, SYS_FLEXE_DIR_RX));

        /* wait until rx switch ok */
        if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A))
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_TX, !curr_active));      
        }
        else
        {
            sal_task_sleep(10);
        }

        /* update group RX flag */
        group_node->rx.active = (SYS_FLEXE_ACTIVE_A == curr_active) ? SYS_FLEXE_ACTIVE_B : SYS_FLEXE_ACTIVE_A;

        /* group sync rx */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_sync(lchip, group_node, SYS_FLEXE_DIR_RX));
        /************************* RX END ************************/
    }

    /* update mac */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_mac(lchip, group_node));

    /************************* group PHY loopback clear ************************/
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_phy_static_cfg(lchip, group_node, is_normal, FALSE));
    CTC_ERROR_RETURN(_sys_tmm_flexe_set_phy_link_intr_mask(lchip, group_node, FALSE));

    if (is_normal)
    {
        /* tx system interrupt callback */
        flexe_event.flag = 0;
        flexe_event.event_type = CTC_FLEXE_EVENT_TX_SWITCH_OK;
        flexe_event.group_num = group_node->group_number;
        _sys_tmm_flexe_intr_cb(lchip, &flexe_event);
        /* rx system interrupt callback */
        flexe_event.flag = 0;
        flexe_event.event_type = CTC_FLEXE_EVENT_RX_SWITCH_OK;
        flexe_event.group_num = group_node->group_number;
        _sys_tmm_flexe_intr_cb(lchip, &flexe_event);
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_set_group_switch_mode(uint8 lchip, sys_flexe_group_t* group_node, uint32 val32)
{
    uint8   diff = 0;
    uint32  tx_c = 0;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /* if switch_mode is same with input val, no need to switch again */
    if (group_node->switch_mode == val32)
    {
        return CTC_E_NONE;
    }

    /* if group has no phy */
    if (!group_node->phy_cnt)
    {
        group_node->switch_mode = val32;

        return CTC_E_NONE;
    }

    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_crcac(lchip, group_node, SYS_FLEXE_DIR_TX, FLEXE_OH_FIELD_TYPE_C_BIT, &tx_c));

    if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A))
    {
        /* if tx.active is different from tx c bit, cannot switch static to dynamic */
        if ((SYS_FLEXE_DYNAMIC_NEGO_SWITCH == val32) && (group_node->tx.active != tx_c))
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] please change group id %d tx active table to %s, then try again!\n", group_node->group_id, (1 == tx_c) ? "B" : "A");
            return CTC_E_INVALID_PARAM;
        }

        if (SYS_FLEXE_STATIC_SWITCH == val32)
        {
            /************************* TX START ************************/
            /* modify switch_sel */
            CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, SYS_FLEXE_DIR_TX, group_node->tx.active));
            /* enable switch_en */
            CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_en(lchip, group_node, SYS_FLEXE_DIR_TX, TRUE));
            /* wait until switch ok */
            CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_TX, group_node->tx.active));
            /************************* TX END **************************/

            /************************* RX START ************************/
            /* modify switchsel */
            CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_sel(lchip, group_node, SYS_FLEXE_DIR_RX, group_node->rx.active));
            /* enable switchen */
            CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_en(lchip, group_node, SYS_FLEXE_DIR_RX, TRUE));
            /* wait until switch ok */
            CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_RX, group_node->rx.active));
            /************************* RX END **************************/
        }
        else
        {
            /* if backup slot is different with running, cannot switch static to dynamic */
            if (SYS_FLEXE_DYNAMIC_NEGO_SWITCH == val32)
            {
                CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_working_backup_slot_diff(lchip, group_node, &diff));
                if (diff)
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group id %d backup config is different from running, cannot switch static to dynamic!\n", group_node->group_id);
                    return CTC_E_INVALID_PARAM;
                }
            }
            /************************* TX START ************************/
            /* modify cr/ca in ohram */
            CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_oh(lchip, group_node, FLEXE_OH_FIELD_TYPE_CR, (void *)&tx_c));
            /* disable switch_en */
            CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_en(lchip, group_node, SYS_FLEXE_DIR_TX, FALSE));
            /* wait until switch ok */
            CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_TX, tx_c));
            /* update inactive slot and ohram, from active to inactive */
            CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_inactive_slot(lchip, group_node, FALSE));
            /************************* TX END **************************/

            /************************* RX START ************************/
            /* disable switch_en */
            CTC_ERROR_RETURN(_sys_tmm_flexe_set_manual_switch_en(lchip, group_node, SYS_FLEXE_DIR_RX, FALSE));
            /************************* RX END **************************/
        }
    }
    else
    {
        if (SYS_FLEXE_DYNAMIC_NEGO_SWITCH == val32)
        {
            /* modify cr/ca in ohram */
            CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_oh(lchip, group_node, FLEXE_OH_FIELD_TYPE_CR, (void *)&tx_c));
            /* update inactive slot and ohram, from active to inactive */
            CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_inactive_slot(lchip, group_node, FALSE));
        }
    }

    group_node->tx.crac_state = SYS_FLEXE_GROUP_TX_IDLE;
    group_node->rx.crac_state = SYS_FLEXE_GROUP_RX_IDLE;

    group_node->switch_mode = val32;

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_static_switch(uint8 lchip, sys_flexe_group_t *group_node, uint32 val)
{
    if (SYS_FLEXE_STATIC_SWITCH != group_node->switch_mode)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group %d switch is %d, CANNOT run static switch\n", \
            group_node->group_id, group_node->switch_mode);
        return CTC_E_INVALID_CONFIG;
    }
    if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A))
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_static_switch_manual(lchip, group_node, val));
    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_static_switch_lb(lchip, group_node, val, TRUE));
    }

    return CTC_E_NONE;
}

#define ____FLEXE_DYNAMIC_SWITCH____

STATIC int32
_sys_tmm_flexe_rxc_2_hw(uint8 lchip, sys_flexe_group_t* group_node, uint32 rx_oh_c)
{
    /* A/B sync */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_sync(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* enable rx_spare */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_set_rx_spare(lchip, group_node, TRUE));

    /* check rx switch ok */
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_RX, rx_oh_c));

    /* disable rx_spare */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_set_rx_spare(lchip, group_node, FALSE));

    return CTC_E_NONE;
}

STATIC int32 
_sys_tmm_flexe_rx_cr_handle(uint8 lchip, sys_flexe_group_t* group_node)
{
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, group %d rx_cr_handle\n", __FUNCTION__, __LINE__, group_node->group_id);

    /* update crcac state */
    group_node->rx.crac_state = SYS_FLEXE_GROUP_RX_CR_RCV;

    /* rx bind slot */
    if (SYS_FLEXE_RX_F0LLOW_REMOTE == group_node->rx_cfg_mode)    //rx follow remote
    {
        /* every client in the group bind slot */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_fill_rx_slot(lchip, group_node, SYS_FLEXE_INACTIVE_FLAG));
    }
    else    //rx local configuration
    {
        /* copy tx cfg slot to rx */
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_cfg_slot_tx2rx(lchip, group_node));
    }

    /* cpy cfg_slot to switch_slot */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_slot_cfg2switch(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* calculate sch */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_gen(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* RX sch config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_config(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* RX flush */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_gen(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* RX flush config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config(lchip, group_node, SYS_FLEXE_DIR_RX));

    return CTC_E_NONE;
}

STATIC int32 
_sys_tmm_flexe_rx_ca_handle(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint8  i           = 0;
    uint8  tmp_inst    = 0;
    uint8  cr_timeout  = 0;
    uint8  is_recv_ca  = TRUE;
    ctc_flexe_status_event_t flexe_event;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, group %d rx_ca_handle\n", __FUNCTION__, __LINE__, group_node->group_id);

    /* update crcac state */
    group_node->tx.crac_state = SYS_FLEXE_GROUP_TX_CA_RCV;

    sal_memset(&flexe_event, 0, sizeof(ctc_flexe_status_event_t));

    /* set receive ca */
    for (i = 0; i < group_node->inst_cnt; i++)
    {
        tmp_inst = group_node->inst_list[i];
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_is_recv_ca_and_cr_timeout(lchip, group_node->flexe_shim_id, (1 << tmp_inst), &is_recv_ca, NULL));
    }

    if (group_node->cr_timer)
    {
        /* check whether cr timeout happens */
        CTC_ERROR_RETURN(_sys_tmm_flexe_get_is_recv_ca_and_cr_timeout(lchip, group_node->flexe_shim_id, group_node->inst_list[0], NULL, &cr_timeout));

        FLEXE_DUMP("\n    [CR_TIMER]%s @ %d, group %d revc ca, and check whether timrout\n", __FUNCTION__, __LINE__, group_node->group_id);
        FLEXE_DUMP("            %-16s : %u\n", "flexe_shim_id", group_node->flexe_shim_id);
        FLEXE_DUMP("            %-16s : %u\n", "asic_inst", group_node->inst_list[0]);
        FLEXE_DUMP("            %-16s : %u [%s]\n", "cr_timeout", cr_timeout, (cr_timeout ? "YES" : "NO"));

        if (cr_timeout)
        {
            FLEXE_DUMP(" [FlexE] %s @ %d cr timeout happens! won't response to the ca!\n", __FUNCTION__, __LINE__);
            return CTC_E_NONE;
        }
        else
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_alarm_cr_timeout(lchip, group_node->group_id, FALSE));
        }
    }

    /* TX sch */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_gen(lchip, group_node, SYS_FLEXE_DIR_TX));

    /* TX sch config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_config(lchip, group_node, SYS_FLEXE_DIR_TX));

    /* TX flush */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_gen(lchip, group_node, SYS_FLEXE_DIR_TX));

    /* TX flush config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config(lchip, group_node, SYS_FLEXE_DIR_TX));

    /* system interrupt callback */
    flexe_event.flag = 0;
    flexe_event.event_type = CTC_FLEXE_EVENT_RCV_CA;
    flexe_event.group_num = group_node->group_number;
    _sys_tmm_flexe_intr_cb(lchip, &flexe_event);

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_rx_c_handle(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint8   curr_active = 0;
    ctc_flexe_status_event_t flexe_event;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, group %d rx_c_handle\n", __FUNCTION__, __LINE__, group_node->group_id);

    /* update crcac state */
    group_node->rx.crac_state = SYS_FLEXE_GROUP_RX_C_RCV;

    sal_memset(&flexe_event, 0, sizeof(ctc_flexe_status_event_t));

    /* set mac FlexE cross */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_mac_cross(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* wait until rx switch ok */
    curr_active = group_node->rx.active;
    if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A))
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_RX, !curr_active));
    }
    else
    {
        sal_task_sleep(10);
    }

    /* update group RX flag */
    group_node->rx.active = (SYS_FLEXE_ACTIVE_A == curr_active) ? SYS_FLEXE_ACTIVE_B : SYS_FLEXE_ACTIVE_A;

    /* rehandle fault */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_ignore_local_fault(lchip, group_node, FALSE));

    /* A/B sync */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_sync(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* update mac */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_mac(lchip, group_node));

    /* flush clear */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config_clear(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* system interrupt callback */
    flexe_event.flag = 0;
    flexe_event.event_type = CTC_FLEXE_EVENT_RX_SWITCH_OK;
    flexe_event.group_num = group_node->group_number;
    _sys_tmm_flexe_intr_cb(lchip, &flexe_event);

    /* update crcac state */
    group_node->rx.crac_state = SYS_FLEXE_GROUP_RX_IDLE;

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_send_cr_handle(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint8 flexe_shim_id  = 0;
    uint8 inst_id        = 0;
    uint8 inst_bmp       = 0;
    uint8 alarm          = 0;
    uint32  val32        = 0;
    uint32  cr           = 0;
    uint32  c            = 0;
    uint8  is_recv_ca    = FALSE;
    uint8  is_timeout    = FALSE;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n ### %s @ %d, group_id: %d\n", __FUNCTION__, __LINE__, group_node->group_id);

    /* check cr/c is same */ 
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_crcac(lchip, group_node, SYS_FLEXE_DIR_TX, FLEXE_OH_FIELD_TYPE_CR, &cr));
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_crcac(lchip, group_node, SYS_FLEXE_DIR_TX, FLEXE_OH_FIELD_TYPE_C_BIT, &c));
    if (cr != c)
    {
        /* if cr != c, let cr as c to keep running. */
        cr = c;
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] group %d previous CR/C flow not complete, allow send CR again\n", group_node->group_id);
    }

    /* check crcac status */ 
    if (SYS_FLEXE_GROUP_TX_IDLE != group_node->tx.crac_state)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] group %d is in %d cr/ca/c state not ready, allow send CR again\n", group_node->tx.crac_state, group_node->group_id);
    }

    /* check alarm of Group_number, instance number, FlexE map */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_check_ohram_alarm(lchip, group_node));
    CTC_ERROR_RETURN(_sys_tmm_flexe_check_ohram_alarm(lchip, group_node, &alarm));
    if (alarm)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group %d mismatch, please check group number/instance number/FlexE map!\n", group_node->group_id);
        return CTC_E_NOT_READY;
    }

    /* clear cr timeout */
    CTC_ERROR_RETURN(_sys_tmm_flexe_alarm_cr_timeout(lchip, group_node->group_id, FALSE));

    /* update inactive slot and ohram, from cfg to inactive */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_inactive_slot(lchip, group_node, TRUE));

    /* send CR */
    val32 = !cr;
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_oh(lchip, group_node, FLEXE_OH_FIELD_TYPE_CR, (void *)&val32));

    /* FlexE CR TIMER */
    if (group_node->cr_timer)
    {
        flexe_shim_id = group_node->flexe_shim_id;

        for (inst_id = 0; inst_id < group_node->inst_cnt; inst_id++)
        {
            inst_bmp |= 1 << group_node->inst_list[inst_id];
        }
        inst_id = group_node->inst_list[0];

        /* init is_recv_ca & is_timeout */
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_is_recv_ca_and_cr_timeout(lchip, flexe_shim_id, inst_bmp, &is_recv_ca, &is_timeout));

        p_usw_flexe_master[lchip]->cr_timer[flexe_shim_id][inst_id].group_id = group_node->group_id;
        p_usw_flexe_master[lchip]->cr_timer[flexe_shim_id][inst_id].inst_bmp = inst_bmp;
        p_usw_flexe_master[lchip]->cr_timer[flexe_shim_id][inst_id].clk_cnt = group_node->cr_timer / SYS_FLEXE_CR_TIMER_POLLING_CLK;
        p_usw_flexe_master[lchip]->cr_timer[flexe_shim_id][inst_id].clk_cnt += (0 == (group_node->cr_timer % SYS_FLEXE_CR_TIMER_POLLING_CLK)) ? 0 : 1;

        FLEXE_DUMP("\n    [CR_TIMER]%s @ %d, group %d set cr timer clk_cnt\n", __FUNCTION__, __LINE__, group_node->group_id);
        FLEXE_DUMP("            %-16s : 0x%x\n", "inst_bmp", p_usw_flexe_master[lchip]->cr_timer[flexe_shim_id][inst_id].inst_bmp);
        FLEXE_DUMP("            %-16s : %u ms\n", "cr_timer", group_node->cr_timer);
        FLEXE_DUMP("            %-16s : %u\n", "clk_cnt", p_usw_flexe_master[lchip]->cr_timer[flexe_shim_id][inst_id].clk_cnt);
    }

    /* update tx status */
    group_node->tx.crac_state = SYS_FLEXE_GROUP_TX_CR_SENT;

    return CTC_E_NONE;
}

STATIC int32 
_sys_tmm_flexe_send_ca_handle(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint32 ca_value = 0;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, group %d send_ca_handle\n", __FUNCTION__, __LINE__, group_node->group_id);

    /* send ca */
    ca_value = (SYS_FLEXE_ACTIVE_A == group_node->rx.active) ? 1 : 0;
    _sys_tmm_flexe_group_send_ca(lchip, group_node, ca_value);

    /* enable rx spare */ 
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_set_rx_spare(lchip, group_node, TRUE));

    /* ignore fault to prevent link down */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_ignore_local_fault(lchip, group_node, TRUE));

    /* update crcac state */
    group_node->rx.crac_state = SYS_FLEXE_GROUP_RX_CA_SENT;

    return CTC_E_NONE;
}

STATIC int32 
_sys_tmm_flexe_send_c_handle(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint32 c_value     = 0;
    uint8  curr_active = 0;
    ctc_flexe_status_event_t flexe_event;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, group %d send_c_handle\n", __FUNCTION__, __LINE__, group_node->group_id);

    sal_memset(&flexe_event, 0, sizeof(ctc_flexe_status_event_t));

    /* write client cal */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_static_send_client_cal(lchip, group_node));

    /* set client datapath which bind port */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_set_datapath(lchip, group_node));

    /* set mac and FlexE cross */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_mac_cross(lchip, group_node, SYS_FLEXE_DIR_TX));

    /* system interrupt callback */
    flexe_event.flag = 0;
    flexe_event.event_type = CTC_FLEXE_EVENT_TX_SWITCH_OK;
    flexe_event.group_num = group_node->group_number;
    _sys_tmm_flexe_intr_cb(lchip, &flexe_event);

    /* Send C */
    curr_active = group_node->tx.active;
    c_value = (SYS_FLEXE_ACTIVE_A == curr_active) ? 1 : 0;
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_oh(lchip, group_node, FLEXE_OH_FIELD_TYPE_C_BIT, (void *)&c_value));

    /* update crcac state */
    group_node->tx.crac_state = SYS_FLEXE_GROUP_TX_C_SENT;

    /* wait until tx switch ok */
    if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A))
    {    
        CTC_ERROR_RETURN(_sys_tmm_flexe_check_group_switch_status(lchip, group_node, SYS_FLEXE_DIR_TX, c_value));
    }
    else
    {
        sal_task_sleep(10);
    }

    /* update group TX flag */
    group_node->tx.active = (SYS_FLEXE_ACTIVE_A == curr_active) ? SYS_FLEXE_ACTIVE_B : SYS_FLEXE_ACTIVE_A;

    /* A/B sync */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_sync(lchip, group_node, SYS_FLEXE_DIR_TX));

    /* update mac */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_mac(lchip, group_node));

    /* flush clear */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config_clear(lchip, group_node, SYS_FLEXE_DIR_TX));

    /* update crcac state */
    group_node->tx.crac_state = SYS_FLEXE_GROUP_TX_IDLE;

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_rollback_send_cr(uint8 lchip, uint32 group_id)
{
    uint32 tx_cr = 0;
    uint32 val32 = 0;
    sys_flexe_group_t* group_node = NULL;

    _sys_tmm_flexe_group_lookup(lchip, group_id, &group_node);
    if (!group_node)
    {
        return CTC_E_NONE;
    }

    group_node->tx.crac_state = SYS_FLEXE_GROUP_TX_IDLE;

    /* rollback cr */
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_crcac(lchip, group_node, SYS_FLEXE_DIR_TX, FLEXE_OH_FIELD_TYPE_CR, &tx_cr));
    val32 = !tx_cr;
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_oh(lchip, group_node, FLEXE_OH_FIELD_TYPE_CR, (void *)&val32));
    /* update inactive slot and ohram, from active to inactive */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_update_inactive_slot(lchip, group_node, FALSE));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_rollback_send_ca(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint32 ca_value = 0;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, group %d recover group\n", __FUNCTION__, __LINE__, group_node->group_id);

    /* rehandle fault */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_ignore_local_fault(lchip, group_node, FALSE));

    /* disable rx spare */ 
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_set_rx_spare(lchip, group_node, FALSE));

    /* send ca */
    ca_value = (SYS_FLEXE_ACTIVE_A == group_node->rx.active) ? 0 : 1;
    _sys_tmm_flexe_group_send_ca(lchip, group_node, ca_value);

    /* update rx state */
    group_node->rx.crac_state = SYS_FLEXE_GROUP_RX_IDLE;

    /* cpy active_slot to cfg_slot */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_slot_active2cfg(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* cpy active_slot to inactive_slot */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_switch_slot_sync(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* calculate sch */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_gen(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* RX sch config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_sch_config(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* RX flush */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_gen(lchip, group_node, SYS_FLEXE_DIR_RX));

    /* RX flush config */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_flush_config(lchip, group_node, SYS_FLEXE_DIR_RX));

    return CTC_E_NONE;
}

STATIC int32 
_sys_tmm_flexe_rx_ca_process(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint32 tx_oh_cr    = 0;
    uint32 rx_oh_ca    = 0;

    /* get tx all_oh_cr */
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_all_crcac(lchip, group_node, SYS_FLEXE_DIR_TX, FLEXE_OH_FIELD_TYPE_CR, &tx_oh_cr));

    /* get rx all_oh_ca */
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_all_crcac(lchip, group_node, SYS_FLEXE_DIR_RX, FLEXE_OH_FIELD_TYPE_CA, &rx_oh_ca));

    /* Check ohram field value with TX active */
    if ((rx_oh_ca == group_node->tx.active) || (tx_oh_cr == group_node->tx.active))
    {
        return CTC_E_NONE;
    }

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] group:%d tx_oh_cr:%d rx_oh_ca:%d sw_table:%d\n", \
        group_node->group_id, tx_oh_cr, rx_oh_ca, group_node->tx.active);

    /* rx ca handle */
    CTC_ERROR_RETURN(_sys_tmm_flexe_rx_ca_handle(lchip, group_node));

    /* send c handle */
    CTC_ERROR_RETURN(_sys_tmm_flexe_send_c_handle(lchip, group_node));

    return CTC_E_NONE;
}

STATIC int32 
_sys_tmm_flexe_rx_cr_c_process(uint8 lchip, sys_flexe_group_t* group_node)
{
    uint32 hw_table     = 0;
    uint32 rx_oh_c      = 0;
    uint32 rx_oh_cr     = 0;
    uint32 tx_oh_ca     = 0;
    uint32 index        = 0;

    /* disable rx_spare */
    CTC_ERROR_RETURN(_sys_tmm_flexe_group_set_rx_spare(lchip, group_node, FALSE));

    /* get rx all_oh_cr */
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_all_crcac(lchip, group_node, SYS_FLEXE_DIR_RX, FLEXE_OH_FIELD_TYPE_CR, &rx_oh_cr));
    
    /* get tx all_oh_ca */
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_all_crcac(lchip, group_node, SYS_FLEXE_DIR_TX, FLEXE_OH_FIELD_TYPE_CA, &tx_oh_ca));

    /* get rx all_oh_c */
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_all_crcac(lchip, group_node, SYS_FLEXE_DIR_RX, FLEXE_OH_FIELD_TYPE_C_BIT, &rx_oh_c));

    /* get hw_table */
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_manual_table(lchip, group_node, SYS_FLEXE_DIR_RX, &hw_table));

    /* get index */
    index = hw_table;
    index |= (group_node->rx.active << 1);
    index |= (rx_oh_c << 2);
    index |= (rx_oh_cr << 3);

    /* all possibility */
    /* Index      bmp         rx_oh_cr    rx_oh_c     sw_table    hw_table      operation
       -------------------------------------------------------------------------------------------------
       0          0000        A           A           A           A             -->Index15
       1          0001        A           A           A           B             -->Index14
       2          0010        A           A           B           A             -->Index13
       3          0011        A           A           B           B             -->Index12
       4          0100        A           B           A           A             -->Index11
       5          0101        A           B           A           B             -->Index10
       6          0110        A           B           B           A             -->Index9
       7          0111        A           B           B           B             -->Index8
       -------------------------------------------------------------------------------------------------
       8          1000        B           A           A           A             rx_cr_handle
       9          1001        B           A           A           B             rx_c_handle, -->Index11
       10         1010        B           A           B           A             rx_c_handle, -->Index8
       11         1011        B           A           B           B             rxc_2_hw,    -->Index10
       12         1100        B           B           A           A             rx_cr_handle
       13         1101        B           B           A           B             rx_c_handle
       14         1110        B           B           B           A             rx_c_handle, -->Index12
       15         1111        B           B           B           B             NA
       -------------------------------------------------------------------------------------------------*/

    /* just for debug */
    if ((((index == 0) || (index == 15)) && (rx_oh_c != tx_oh_ca)) || ((index > 0) && (index < 15)))
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] group:%d case_index:%d rx_oh_cr:%d rx_oh_c:%d sw_table:%d hw_table:%d\n", \
            group_node->group_id, index, rx_oh_cr, rx_oh_c, group_node->rx.active, hw_table);
    }

    /* transfer index to 8 ~ 15 */
    if (index <= 7)
    {
        index = 15 - index;
    }

    /* process */
    switch (index)
    {
    case 15:
        /* rollback rx_cr_handle and send ca */
        if (rx_oh_c != tx_oh_ca)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_rollback_send_ca(lchip, group_node));
        }
        break;
    case 8:
    case 12:
        /* rx_cr_handle and send ca */
        CTC_ERROR_RETURN(_sys_tmm_flexe_rx_cr_handle(lchip, group_node));
        CTC_ERROR_RETURN(_sys_tmm_flexe_send_ca_handle(lchip, group_node));
        break;
    case 11:
        /* enable rx_spare */
        CTC_ERROR_RETURN(_sys_tmm_flexe_rxc_2_hw(lchip, group_node, rx_oh_c));
        break;
    case 9:
    case 10:
    case 13:
    case 14:
        /* rx_c_handle */
        CTC_ERROR_RETURN(_sys_tmm_flexe_rx_c_handle(lchip, group_node));
        break;
    default:
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] Invalid condition! case_index:%d rx_oh_cr:%d rx_oh_c:%d hw_table:%d sw_table:%d\n", \
            index, rx_oh_cr, rx_oh_c, hw_table, group_node->rx.active);
        return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_dynamic_nego_switch(uint8 lchip, sys_flexe_group_t *group_node)
{
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, group %d dynamic_nego_switch\n", __FUNCTION__, __LINE__, group_node->group_id);

    if (SYS_FLEXE_DYNAMIC_NEGO_SWITCH != group_node->switch_mode)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] only dynamic negotiation mode can send CR!\n");
        return CTC_E_INVALID_CONFIG;
    }

    if (0 == group_node->phy_cnt)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group %d not bind phy, CANNOT send CR\n", group_node->group_id);
        return CTC_E_INVALID_CONFIG;
    }

    CTC_ERROR_RETURN(_sys_tmm_flexe_send_cr_handle(lchip, group_node));

    return CTC_E_NONE;
}

#define ____FLEXE_SYS_API____

/**
 @brief set flexe module enable
*/
int32
sys_tmm_flexe_set_en(uint8 lchip, uint16 serdes_id, uint8 enable)
{
    uint8 flexe_shim_id = 0;
    uint8 cs_id         = 0;

    /* 1. param check */
    /* 1.1, illegal serdes id */
    flexe_shim_id = SYS_TMM_FLEXE_GET_FLEXE_SHIM(serdes_id);
    if (SYS_FLEXE_UNSUPP == flexe_shim_id)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] SerDes ID %d not support FlexE \n", serdes_id);
        return CTC_E_NOT_SUPPORT;
    }

    SYS_TMM_FLEXE_SERDES_2_CS(serdes_id, cs_id);
    if (enable)
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_enable(lchip, cs_id));
    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_disable(lchip, cs_id));
    }

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_get_en(uint8 lchip, uint16 serdes_id, uint8 *enable)
{
    uint8 cs_id = 0;

    SYS_TMM_FLEXE_SERDES_2_CS(serdes_id, cs_id);
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_enable(lchip, cs_id, enable));
    return CTC_E_NONE;
}

int32
sys_tmm_flexe_create_group(uint8 lchip, uint32 group_id, ctc_flexe_grp_t* p_group)
{
    int32 ret = CTC_E_NONE;
    sys_flexe_group_t* group_node = NULL;

    _sys_tmm_flexe_group_lookup(lchip, group_id, &group_node);
    if (group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group ID %d aleady exists!\n", group_id);
        return CTC_E_ENTRY_EXIST;
    }
    group_node = (sys_flexe_group_t*)mem_malloc(MEM_DMPS_MODULE, sizeof(sys_flexe_group_t));
    if (NULL == group_node)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(group_node, 0, sizeof(sys_flexe_group_t));

    /* init group ds */
    _sys_tmm_flexe_init_group_ds(lchip, group_node);

    /* add group to list */
    ctc_slist_add_tail(p_usw_flexe_master[lchip]->group_list, &(group_node->head));
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_FLEXE, SYS_WB_APPID_FLEXE_SUBID_GROUP, 1);

    group_node->group_id = group_id;
    group_node->switch_mode = p_group->flag;
    group_node->rx_cfg_mode = SYS_FLEXE_RX_F0LLOW_REMOTE;

    ret = _sys_tmm_flexe_set_group_number(lchip, group_node, p_group->group_num);
    if (ret)
    {
        mem_free(group_node);
        return ret;
    }

    if (p_group->phy.serdes_cnt)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Not support create group with PHY list!\n");
        mem_free(group_node);
        return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_destroy_group(uint8 lchip, uint32 group_id)
{
    sys_flexe_group_t* group_node = NULL;
    ctc_slistnode_t        *node = NULL;

    sys_flexe_client_t* client_node = NULL;

    _sys_tmm_flexe_group_lookup(lchip, group_id, &group_node);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group ID %d not exist!\n", group_id);
        return CTC_E_NOT_EXIST;
    }

    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
    {
        client_node = _ctc_container_of(node, sys_flexe_client_t, head);
        if (client_node && (group_id == client_node->group_id))
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group ID %d client list not empty, please empty client first!\n", group_id);
            return CTC_E_INVALID_PARAM;
        }
    }

    if (group_node->inst_cnt || group_node->phy_cnt)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group ID %d phy list not empty, please empty phy first!\n", group_id);
        return CTC_E_NOT_READY;
    }

    _sys_tmm_flexe_init_group_ds(lchip, group_node);

    node = &(group_node->head);
    ctc_slist_delete_node(p_usw_flexe_master[lchip]->group_list, node);
    mem_free(group_node);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_FLEXE, SYS_WB_APPID_FLEXE_SUBID_GROUP, 1);

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_get_group(uint8 lchip, uint32 group_id, ctc_flexe_grp_t* p_group)
{
    uint8 i = 0;
    uint8 physical_serdes_id = 0;
    sys_flexe_group_t* group_node = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, get group %d\n", __FUNCTION__, __LINE__, group_id);

    if (!p_group)
    {
        return CTC_E_NO_MEMORY;
    }

    _sys_tmm_flexe_group_lookup(lchip, group_id, &group_node);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group ID %d not exist!\n", group_id);
        return CTC_E_NOT_EXIST;
    }

    p_group->group_num      = group_node->group_number;
    p_group->phy.serdes_cnt = group_node->phy_cnt;
    p_group->flag           = (SYS_FLEXE_STATIC_SWITCH == group_node->switch_mode) ? 1 : 0;
    if (p_group->phy.serdes_id)
    {
        for (i = 0; i < p_group->phy.serdes_cnt; i++)
        {
            CTC_ERROR_RETURN(_sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, group_node->phy_list[i].logical_serdes_base, &physical_serdes_id));
            p_group->phy.serdes_id[i] = physical_serdes_id;
        }
    }

    return CTC_E_NONE;
}


int32
sys_tmm_flexe_add_client(uint8 lchip, uint32 client_id, ctc_flexe_client_t* p_client)
{
    sys_flexe_client_t* client_node = NULL;

    _sys_tmm_flexe_client_lookup(lchip, client_id, &client_node);
    if (client_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d aleady exists!\n", client_id);
        return CTC_E_ENTRY_EXIST;
    }

    client_node = (sys_flexe_client_t*)mem_malloc(MEM_DMPS_MODULE, sizeof(sys_flexe_client_t));
    if (NULL == client_node)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(client_node, 0, sizeof(sys_flexe_client_t));

    /* init client ds */
    _sys_tmm_flexe_init_client_ds(lchip, client_node);

    /* add client to list */
    ctc_slist_add_tail(p_usw_flexe_master[lchip]->client_list, &(client_node->head));
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_FLEXE, SYS_WB_APPID_FLEXE_SUBID_CLIENT, 1);

    client_node->client_id = client_id;

    if (p_client)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Not support add client with parameters!\n");
        mem_free(client_node);
        return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_remove_client(uint8 lchip, uint32 client_id)
{
    sys_flexe_client_t* client_node = NULL;

    _sys_tmm_flexe_client_lookup(lchip, client_id, &client_node);
    if (!client_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d not exist!\n", client_id);
        return CTC_E_ENTRY_NOT_EXIST;
    }

    CTC_ERROR_RETURN(_sys_tmm_flexe_remove_client_pc(lchip, client_id));

    CTC_ERROR_RETURN(sys_tmm_flexe_remove_client_node(lchip, client_node));

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_get_client(uint8 lchip, uint32 client_id, ctc_flexe_client_t* p_client)
{
    uint8 i = 0;
    uint8 j = 0;
    uint8 flag = 0;
    uint8 speed_mode = 0;
    uint8 phy_inst_cnt = 0;
    uint8 slot = 0;
    uint8 slot_heng = 0;
    uint8 slot_per_phy = 0;
    uint8 group_inst_offset = 0;
    uint8 physical_serdes_id = 0;
    uint8 phy_cnt = 0;  /* cnt of phy in the group */
    uint8 phy_cnt_valid = 0;  /* cnt of phy which has the client's slot */
    sys_flexe_group_t* group_node = NULL;
    sys_flexe_client_t* client_node = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, get client property %d\n", __FUNCTION__, __LINE__, client_id);

    if (!p_client)
    {
        return CTC_E_NO_MEMORY;
    }

    _sys_tmm_flexe_client_lookup(lchip, client_id, &client_node);
    if (!client_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d not exist!\n", client_id);
        return CTC_E_NOT_EXIST;
    }

    _sys_tmm_flexe_group_lookup(lchip, client_node->group_id, &group_node);
    if (!group_node)
    {
        p_client->client_num = client_node->client_number;
        p_client->group_id   = SYS_FLEXE_UNUSED_FLAG_U32;
        p_client->slot.phy_cnt = 0;
    } 
    else
    {
        p_client->client_num = client_node->client_number;
        p_client->group_id   = client_node->group_id;

        _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);
        phy_inst_cnt = SYS_TMM_FLEXE_PHY_2_INST_CNT(speed_mode);

        for (phy_cnt = 0; phy_cnt < group_node->phy_cnt; phy_cnt++)
        {
            CTC_ERROR_RETURN(_sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, group_node->phy_list[phy_cnt].logical_serdes_base, &physical_serdes_id));
            p_client->slot.slot[phy_cnt_valid].serdes_id = physical_serdes_id;
            for (i = group_node->phy_list[phy_cnt].inst_base; i < (group_node->phy_list[phy_cnt].inst_base + phy_inst_cnt); i++)
            {
                _sys_tmm_flexe_get_group_inst_offset_by_asic_inst(lchip, group_node, i, &group_inst_offset);            
                for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
                {
                    if ((group_node->tx.dir_inst[group_inst_offset].slot_cfg_shim_chid[j]) == client_node->shim_chid)
                    {
                        slot = group_node->inst_list[group_inst_offset]*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) + j; 
                        (void)_sys_tmm_flexe_slot_shu2heng(lchip, group_node, slot, &slot_heng);
                        /* fill p_slot slot_bmp */
                        slot_per_phy = slot_heng - group_node->phy_list[phy_cnt].inst_base*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST);
                        CTC_BMP_SET(p_client->slot.slot[phy_cnt_valid].slot_bmp, slot_per_phy);
                        flag = 1;
                    }
                }
            }
            if (flag)
            {
                phy_cnt_valid++;
                flag = 0;
            }
        }
        p_client->slot.phy_cnt = phy_cnt_valid;
    }

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_set_group_property(uint8 lchip, uint32 group_id, ctc_flexe_grp_prop_t group_prop, void* p_value)
{
    uint32  val32 = 0;
    uint32  enable = 0;
    //int32   ret   = 0;
    sys_flexe_group_t* group_node = NULL;
    ctc_flexe_phy_t*   phy_list   = NULL;
    //sys_flexe_client_chg_t *client_chg = NULL;

    _sys_tmm_flexe_group_lookup(lchip, group_id, &group_node);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group ID %d not exist!\n", group_id);
        return CTC_E_NOT_EXIST;
    }

    switch (group_prop)
    {
    case CTC_FLEXE_GRP_PROP_GRP_NUM:
        val32 = *((uint32*)p_value);
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_group_number(lchip, group_node, val32));
        break;
    case CTC_FLEXE_GRP_PROP_PHY:
        phy_list = (ctc_flexe_phy_t*)p_value;
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_set_phylist(lchip, group_node, phy_list));
        break;
    case CTC_FLEXE_GRP_PROP_CAL_SEL:
        val32 = *((uint32*)p_value);
        if ((SYS_FLEXE_ACTIVE_A != val32) && (SYS_FLEXE_ACTIVE_B != val32))
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] cal-sel only support 0(A) and 1(B)!\n");
            return CTC_E_INVALID_PARAM;
        }
        if (0 == group_node->phy_cnt)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] group %d not bind phylist, CANNOT run static switch!\n", group_node->group_id);
            return CTC_E_INVALID_PARAM;
        }
        CTC_ERROR_RETURN(_sys_tmm_flexe_static_switch(lchip, group_node, val32));
        break;
    case CTC_FLEXE_GRP_PROP_SWITCH_TRIGGER:
        CTC_ERROR_RETURN(_sys_tmm_flexe_dynamic_nego_switch(lchip, group_node));
        break;
    case CTC_FLEXE_GRP_PROP_SWITCH_MODE:
        val32 = *((uint32*)p_value);
        if ((0 != val32) && (CTC_FLEXE_GRP_FLAG_MANUAL != val32))
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Invaild switch mode value %d!\n", val32);
            return CTC_E_INVALID_PARAM;
        }
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_group_switch_mode(lchip, group_node, val32));
        break;
    case CTC_FLEXE_GRP_PROP_CR_TIMER:
        group_node->cr_timer = *((uint32*)p_value);
        if (0 == group_node->cr_timer)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_alarm_cr_timeout(lchip, group_node->group_id, FALSE));
        }
        break;
    case CTC_FLEXE_GRP_PROP_SYNC_MSG_EN:
        enable = *((uint32*)p_value);
        if (0 == group_node->phy_cnt)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] cannot set sync messaging channel when group is empty!\n");
            return CTC_E_INVALID_PARAM;
        }
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_cfgrxoh_sync(lchip, group_node, enable));
        CTC_ERROR_RETURN(_sys_tmm_flexe_group_ow_oh(lchip, group_node, FLEXE_OH_FIELD_TYPE_SC, (void*)&enable));
        break;
    case CTC_FLEXE_GRP_PROP_PAD_EN:
        if (group_node->phy_cnt)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] please set group phy paden when group is empty!\n");
            return CTC_E_INVALID_PARAM;
        }
        group_node->pad_en = *((uint8*)p_value);
        break;
    default:
        return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_get_group_property(uint8 lchip, uint32 group_id, ctc_flexe_grp_prop_t group_prop, void* p_value)
{
    int8 i = 0;
    uint32 enable = 0;
    uint8 speed_mode = 0;
    uint8 physical_serdes_id = 0;
    sys_flexe_group_t* group_node = NULL;
    ctc_flexe_phy_t* p_flexe_phy = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, get group property %d\n", __FUNCTION__, __LINE__, group_id);

    _sys_tmm_flexe_group_lookup(lchip, group_id, &group_node);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group ID %d not exist!\n", group_id);
        return CTC_E_NOT_EXIST;
    }

    switch (group_prop)
    {
    case CTC_FLEXE_GRP_PROP_GRP_NUM:
        *((uint32*)p_value) = group_node->group_number;
        break;
    case CTC_FLEXE_GRP_PROP_PHY:
        p_flexe_phy = (ctc_flexe_phy_t*)p_value;
        p_flexe_phy->serdes_cnt = group_node->phy_cnt;
        for (i = 0; i < group_node->phy_cnt; i++)
        {
            CTC_ERROR_RETURN(_sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, group_node->phy_list[i].logical_serdes_base, &physical_serdes_id));
            p_flexe_phy->serdes_id[i] = physical_serdes_id;
        }
        break;
    case CTC_FLEXE_GRP_PROP_SWITCH_MODE:
        *((uint32*)p_value) = (uint32)group_node->switch_mode;
        break;
    case CTC_FLEXE_GRP_PROP_CAL_SEL:
        if (SYS_FLEXE_STATIC_SWITCH != group_node->switch_mode)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Only static switch support calendar selection!\n");
            return CTC_E_INVALID_PARAM;
        }
        *((uint32*)p_value) = (uint32)group_node->tx.active;
        break;
    case CTC_FLEXE_GRP_PROP_CR_TIMER:
        *((uint32*)p_value) = group_node->cr_timer;
        break;
    case CTC_FLEXE_GRP_PROP_SYNC_MSG_EN:
        if (0 == group_node->phy_cnt)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] cannot get sync messaging channel when group is empty!\n");
            return CTC_E_INVALID_PARAM;
        }
        CTC_ERROR_RETURN(_sys_tmm_flexe_get_cfgrxoh_sync(lchip, group_node, &enable));
        *((uint32*)p_value) = enable;
        break;
    case CTC_FLEXE_GRP_PROP_PAD_EN:
        _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);
        if (CTC_PORT_SPEED_50G != speed_mode)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] only LG PHY can get pad enable/disale!\n");
            return CTC_E_INVALID_PARAM;
        }
        *((uint8*)p_value) = group_node->pad_en;
        break;
    case CTC_FLEXE_GRP_PROP_SWITCH_TRIGGER:
    default:
        return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}


int32
sys_tmm_flexe_set_client_property(uint8 lchip, uint32 client_id, uint32 client_prop, void* p_value)
{
    uint32  val32 = 0;
    uint8   val8  = 0;
    sys_flexe_client_t* client_node = NULL;
    ctc_flexe_client_slot_t* p_slot      = NULL;

    _sys_tmm_flexe_client_lookup(lchip, client_id, &client_node);
    if (!client_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d not exist!\n", client_id);
        return CTC_E_NOT_EXIST;
    }

    switch (client_prop)
    {
    case CTC_FLEXE_CLIENT_PROP_GROUP_ID:
        val32 = *((uint32*)p_value);
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_set_group(lchip, client_node, val32));
        break;
    case CTC_FLEXE_CLIENT_PROP_CLIENT_NUM:
        val32 = *((uint32*)p_value);
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_client_number(lchip, client_node, val32));
        break;
    case CTC_FLEXE_CLIENT_PROP_BINDING_PORT:
        val32 = *((uint32*)p_value);
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_bind_port(lchip, client_node, val32));
        break;
    case CTC_FLEXE_CLIENT_PROP_SLOT:
        p_slot = (ctc_flexe_client_slot_t*)p_value;
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_bind_slot(lchip, client_node, p_slot));
        break;
    case CTC_FLEXE_CLIENT_PROP_TX_RX:
        val32 = *((uint32*)p_value);
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_set_mcmac_tx_rx_en(lchip, &client_node, val32));
        break;
    case SYS_FLEXE_CLIENT_PROP_BIND_OAM:
        val32 = *((uint32*)p_value);
        client_node->bind_oam = val32?1:0;
        break;
    case CTC_FLEXE_CLIENT_PROP_MAC_EN:
        val8 = *((uint32*)p_value) ? 1 : 0;
        if (SYS_FLEXE_UNUSED_FLAG_U16 != client_node->mac_id)
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_set_client_mac_en(lchip, client_node, val8));
        }
        else
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d has no mac!\n", client_node->client_id);
            return CTC_E_INVALID_PARAM;
        }
        break;
    case CTC_FLEXE_CLIENT_PROP_RX_RECOVER:
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_force_recover(lchip, client_node));
        break;
    default:
        return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_get_client_property(uint8 lchip, uint32 client_id, uint32 client_prop, void* p_value)
{
    uint8 val8 = 0;
    uint32 speed = 0;
    sys_flexe_client_t* client_node = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, get client property %d\n", __FUNCTION__, __LINE__, client_id);

    _sys_tmm_flexe_client_lookup(lchip, client_id, &client_node);
    if (!client_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d not exist!\n", client_id);
        return CTC_E_NOT_EXIST;
    }

    switch (client_prop)
    {
    case CTC_FLEXE_CLIENT_PROP_GROUP_ID:
        *((uint32*)p_value) = client_node->group_id;
        break;
    case CTC_FLEXE_CLIENT_PROP_CLIENT_NUM:
        *((uint32*)p_value) = client_node->client_number;
        break;
    case CTC_FLEXE_CLIENT_PROP_BINDING_PORT:
        *((uint32*)p_value) = client_node->gport;
        break;
    case CTC_FLEXE_CLIENT_PROP_SLOT:
        CTC_ERROR_RETURN(_sys_tmm_flexe_get_client_slot(lchip, client_node, p_value));
        break;
    case CTC_FLEXE_CLIENT_PROP_TX_RX:
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_get_mcmac_tx_rx_en(lchip, &client_node, p_value));
        break;
    case SYS_FLEXE_CLIENT_PROP_HW_CLIENT:
        if (SYS_FLEXE_UNUSED_FLAG_U32 == client_node->group_id)
        {
            return CTC_E_NOT_EXIST;
        }
        *((uint16*)p_value) = client_node->tx_xc_chid + (client_node->flexe_shim_id? MCHIP_CAP(SYS_CAP_FLEXE_MAX_CLIENT) : 0);
        break;
    case CTC_FLEXE_CLIENT_PROP_MAC_EN:
        if (SYS_FLEXE_UNUSED_FLAG_U16 != client_node->mac_id)
        {
            CTC_ERROR_RETURN(_sys_tmm_mac_get_flexe_mac_en(lchip, client_node->mac_id, SYS_FLEXE_DIR_TX, &val8));
            *((uint32*)p_value) = (val8 ? 1 : 0);
        }
        else
        {
            *((uint32*)p_value) = FALSE;
        }
        break;
    case CTC_FLEXE_CLIENT_PROP_SPEED:
        _sys_tmm_flexe_get_client_speed_val(lchip, client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_INACTIVE_FLAG, &speed);
        *((uint32*)p_value) = speed/SYS_FLEXE_SLOT_SPEED;
        break;
    default:
        return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}


int32
sys_tmm_flexe_get_client_link_up(uint8 lchip, uint32 client_id, uint8* p_is_up)
{
    uint8  match            = 0;
    uint8  active_rx_slot   = 0;
    uint32 mac_id           = 0;
    sys_flexe_client_t* client_node = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /* 1, check client exist */
    _sys_tmm_flexe_client_lookup(lchip, client_id, &client_node);
    if (!client_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d not exist!\n", client_id);
        return CTC_E_NOT_EXIST;
    }

    /* 2, check client mac */
    mac_id = client_node->mac_id;
    if (SYS_FLEXE_UNUSED_FLAG_U16 == mac_id)
    {
        SYS_USW_VALID_PTR_WRITE(p_is_up, 0);
        return CTC_E_NONE;
    }

    /* 3, check client rx speed */
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_hw_client_slot_cnt(lchip, client_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_ACTIVE_FLAG, &active_rx_slot));
    if (!active_rx_slot)
    {
        SYS_USW_VALID_PTR_WRITE(p_is_up, 0);
        return CTC_E_NONE;
    }

    /* 4, check Mii status */
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_client_mii_link_status(lchip, client_node, p_is_up));
    if (0 == *p_is_up)
    {
        return CTC_E_NONE;
    }

    /* 5, check client match */
    CTC_ERROR_RETURN(sys_tmm_flexe_check_client_match(lchip, client_node, &match));
    if (!match)
    {
        *p_is_up = 0;
        return CTC_E_NONE;
    }

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_set_client_cross(uint8 lchip, ctc_flexe_cross_t* p_cross)
{
    sys_flexe_client_calcfg_t flexe_client_cal[SYS_FLEXE_MAX_CYCLE];
    sys_flexe_client_t* src_client_node = NULL;
    sys_flexe_client_t* dest_client_node = NULL;
    sys_flexe_client_flow_t flow_type = 0;
    uint8 is_ret = 0;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, set client %d cross connect to client %d\n", 
        __FUNCTION__, __LINE__, p_cross->client_id, p_cross->dest_client_id);

    CTC_ERROR_RETURN(_sys_tmm_flexe_client_cross_pc(lchip, p_cross, &is_ret));
    if (is_ret)
    {
        return CTC_E_NONE;
    }

    _sys_tmm_flexe_client_lookup(lchip, p_cross->client_id, &src_client_node);
    _sys_tmm_flexe_client_lookup(lchip, p_cross->dest_client_id, &dest_client_node);

    if (src_client_node->flexe_shim_id == dest_client_node->flexe_shim_id)
    {
        flow_type = SYS_FLEXE_FLOW_TYPE_C;
    }
    else
    {
        flow_type = SYS_FLEXE_FLOW_TYPE_A;
    }

    if (p_cross->enable)
    {
        src_client_node->flow_type = flow_type;
        dest_client_node->flow_type = flow_type;
        dest_client_node->rx_xc_chid = src_client_node->tx_xc_chid;
        src_client_node->rx_xc_chid = dest_client_node->tx_xc_chid;

        /* step 0, soft table update */
        //CTC_ERROR_RETURN(_sys_tmm_flexe_client_cal_update(lchip));

        /* Dest client */
        /* step 1 */
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_writemask(lchip, dest_client_node->flexe_shim_id, dest_client_node->tx_xc_chid, SYS_FLEXE_FLOW_TYPE_B, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_mcfifo_writemask(lchip, dest_client_node->flexe_shim_id, dest_client_node->tx_xc_chid, FALSE));

        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_writemask(lchip, dest_client_node->flexe_shim_id, dest_client_node->rx_xc_chid, flow_type, TRUE));
        /* step 2 */
        CTC_ERROR_RETURN(_sys_tmm_flexe_shim_cal_gen(lchip, dest_client_node->flexe_shim_id, SYS_FLEXE_DIR_TX, flexe_client_cal));
        CTC_ERROR_RETURN(_sys_tmm_flexe_cross_cal_config(lchip, dest_client_node->flexe_shim_id, flexe_client_cal));
        /* step 3 */
        CTC_ERROR_RETURN(_sys_tmm_flexe_fifo_read_cfg(lchip, dest_client_node, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp(lchip, dest_client_node, flow_type, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_fifo_full_thrd(lchip, dest_client_node, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_remove_idle_thrd(lchip, dest_client_node, flow_type, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_insert_idle_thrd(lchip, dest_client_node, flow_type, TRUE));
        /* step 4 */

        /* Src client */
        /* step 1 */
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_writemask(lchip, src_client_node->flexe_shim_id, src_client_node->tx_xc_chid, SYS_FLEXE_FLOW_TYPE_B, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_mcfifo_writemask(lchip, src_client_node->flexe_shim_id, src_client_node->tx_xc_chid, FALSE));

        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_writemask(lchip, src_client_node->flexe_shim_id, src_client_node->rx_xc_chid, flow_type, TRUE));
        /* step 2 */
        CTC_ERROR_RETURN(_sys_tmm_flexe_shim_cal_gen(lchip, src_client_node->flexe_shim_id, SYS_FLEXE_DIR_TX, flexe_client_cal));
        CTC_ERROR_RETURN(_sys_tmm_flexe_cross_cal_config(lchip, src_client_node->flexe_shim_id, flexe_client_cal));
        /* step 3 */
        CTC_ERROR_RETURN(_sys_tmm_flexe_fifo_read_cfg(lchip, src_client_node, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp(lchip, src_client_node, flow_type, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_fifo_full_thrd(lchip, src_client_node, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_remove_idle_thrd(lchip, src_client_node, flow_type, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_insert_idle_thrd(lchip, src_client_node, flow_type, TRUE));
        /* step 4 */

    }
    else
    {
        /* Dest client */
        /* step 1 */
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_writemask(lchip, dest_client_node->flexe_shim_id, dest_client_node->rx_xc_chid, flow_type, FALSE));
        /* step 2 */
        CTC_ERROR_RETURN(_sys_tmm_flexe_shim_cal_gen(lchip, dest_client_node->flexe_shim_id, SYS_FLEXE_DIR_TX, flexe_client_cal));
        CTC_ERROR_RETURN(_sys_tmm_flexe_cross_cal_config(lchip, dest_client_node->flexe_shim_id, flexe_client_cal));
        /* step 3 */
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp(lchip, dest_client_node, flow_type, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_remove_idle_thrd(lchip, dest_client_node, flow_type, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_insert_idle_thrd(lchip, dest_client_node, flow_type, FALSE));
        /* step 4 */
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_writemask(lchip, dest_client_node->flexe_shim_id, dest_client_node->tx_xc_chid, SYS_FLEXE_FLOW_TYPE_B, TRUE));

        /* Src client */
        /* step 1 */
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_writemask(lchip, src_client_node->flexe_shim_id, src_client_node->rx_xc_chid, flow_type, FALSE));
        /* step 2 */
        CTC_ERROR_RETURN(_sys_tmm_flexe_shim_cal_gen(lchip, src_client_node->flexe_shim_id, SYS_FLEXE_DIR_TX, flexe_client_cal));
        CTC_ERROR_RETURN(_sys_tmm_flexe_cross_cal_config(lchip, src_client_node->flexe_shim_id, flexe_client_cal));
        /* step 3 */
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp(lchip, src_client_node, flow_type, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_remove_idle_thrd(lchip, src_client_node, flow_type, FALSE));
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_insert_idle_thrd(lchip, src_client_node, flow_type, FALSE));
        /* step 4 */
        CTC_ERROR_RETURN(_sys_tmm_flexe_rate_comp_writemask(lchip, src_client_node->flexe_shim_id, src_client_node->tx_xc_chid, SYS_FLEXE_FLOW_TYPE_B, TRUE));

        flow_type = SYS_FLEXE_FLOW_TYPE_B;
        src_client_node->flow_type = flow_type;
        dest_client_node->flow_type = flow_type;
        dest_client_node->rx_xc_chid = dest_client_node->tx_xc_chid;
        src_client_node->rx_xc_chid = src_client_node->tx_xc_chid;

        /* soft table update, cfg datapath and cross */
        CTC_ERROR_RETURN(_sys_tmm_flexe_shim_cal_gen(lchip, dest_client_node->flexe_shim_id, SYS_FLEXE_DIR_TX, flexe_client_cal));
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_cross_config(lchip, dest_client_node, SYS_FLEXE_DIR_TX, flexe_client_cal));

        CTC_ERROR_RETURN(_sys_tmm_flexe_shim_cal_gen(lchip, src_client_node->flexe_shim_id, SYS_FLEXE_DIR_TX, flexe_client_cal));
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_cross_config(lchip, src_client_node, SYS_FLEXE_DIR_TX, flexe_client_cal));

        CTC_ERROR_RETURN(_sys_tmm_flexe_shim_cal_gen(lchip, dest_client_node->flexe_shim_id, SYS_FLEXE_DIR_RX, flexe_client_cal));
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_cross_config(lchip, dest_client_node, SYS_FLEXE_DIR_RX, flexe_client_cal));

        CTC_ERROR_RETURN(_sys_tmm_flexe_shim_cal_gen(lchip, src_client_node->flexe_shim_id, SYS_FLEXE_DIR_RX, flexe_client_cal));
        CTC_ERROR_RETURN(_sys_tmm_flexe_client_cross_config(lchip, src_client_node, SYS_FLEXE_DIR_RX, flexe_client_cal));
    }

    if (p_cross->enable)
    {
        src_client_node->cross_client_id = dest_client_node->client_id;
        dest_client_node->cross_client_id = src_client_node->client_id;
        src_client_node->cross_enable = TRUE;
        dest_client_node->cross_enable = TRUE;
    }
    else
    {
        src_client_node->cross_client_id = 0;
        dest_client_node->cross_client_id = 0;
        src_client_node->cross_enable = FALSE;
        dest_client_node->cross_enable = FALSE;
    }

    return CTC_E_NONE;
}


int32
sys_tmm_flexe_get_client_cross(uint8 lchip, ctc_flexe_cross_t* p_cross)
{
    sys_flexe_client_t* client_node = NULL;

    _sys_tmm_flexe_client_lookup(lchip, p_cross->client_id, &client_node);
    if (!client_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d not exist!\n", p_cross->client_id);
        return CTC_E_NOT_EXIST;
    }
    if (client_node->cross_enable && (client_node->cross_client_id == p_cross->dest_client_id))
    {
        p_cross->enable = TRUE;
    }
    else
    {
        p_cross->enable = FALSE;
    }

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_set_phy_property(uint8 lchip, uint16 serdes_id, ctc_flexe_phy_prop_t phy_prop, void* p_value)
{
    uint32 val32    = 0;
    uint8  flexe_en = 0;
    uint8  cs_id    = 0;

    SYS_TMM_FLEXE_SERDES_2_CS(serdes_id, cs_id);
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_enable(lchip, cs_id, &flexe_en));
    if (!flexe_en)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] SerDes ID %d not enable FlexE \n", serdes_id);
        return CTC_E_NOT_READY;
    }

    switch (phy_prop)
    {
    case CTC_FLEXE_PHY_PROP_PHY_NUM:
        val32 = *((uint32*)p_value);
        CTC_ERROR_RETURN(_sys_tmm_flexe_set_phy_number(lchip, serdes_id, val32));
        break;
    case CTC_FLEXE_PHY_PROP_SLOT:
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] This API only support get operation \n");
        return CTC_E_NOT_SUPPORT;
    default:
        break;
    }

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_get_phy_property(uint8 lchip, uint16 serdes_id, ctc_flexe_phy_prop_t phy_prop, void* p_value)
{
    uint8 logical_serdes_id = 0;
    sys_flexe_phy_t* phy_node = NULL;
    sys_flexe_group_t* group_node = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, get phy property %d\n", __FUNCTION__, __LINE__, serdes_id);

    CTC_ERROR_RETURN(_sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, serdes_id, &logical_serdes_id));
    group_node = _sys_tmm_flexe_group_lookup_by_serdes(lchip, logical_serdes_id);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] phy %d has not added to any FlexE group!\n", logical_serdes_id);
        return CTC_E_NOT_EXIST;
    }
    phy_node = _sys_tmm_flexe_get_phy_node(lchip, logical_serdes_id);
    if (!phy_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] phy %d has not added to any FlexE group!\n", logical_serdes_id);
        return CTC_E_NOT_EXIST;
    }

    switch (phy_prop)
    {
    case CTC_FLEXE_PHY_PROP_PHY_NUM:
        *((uint32*)p_value) = phy_node->phy_number;
        break;
    case CTC_FLEXE_PHY_PROP_SLOT:
        CTC_ERROR_RETURN(_sys_tmm_flexe_get_phy_timeslot(lchip, group_node, phy_node, p_value));
        break;
    case CTC_FLEXE_PHY_PROP_OH_INFO:
        CTC_ERROR_RETURN(_sys_tmm_flexe_get_phy_ohram_info(lchip, group_node, phy_node, p_value));
        break;
    case CTC_FLEXE_PHY_PROP_CRC_CNT:
        *((uint32*)p_value) = phy_node->crc_cnt;
        break;
    default:
        break;
    }

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_get_phy_inst_id(uint8 lchip, uint8 dp_id, uint8 asic_inst_id, uint8* p_serdes_id, uint32* p_instance_id)
{
    uint8 logical_serdes_id = 0;
    uint8 speed_mode = 0;
    sys_flexe_group_t* group_node = NULL;
    sys_flexe_phy_t*   phy_node   = NULL;

    if (!p_serdes_id || !p_instance_id)
    {
        return CTC_E_NO_MEMORY;
    }

    group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, dp_id, asic_inst_id);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Asic inst %d not belong to any group!\n", asic_inst_id);
        return CTC_E_INVALID_PARAM;
    }
    phy_node = _sys_tmm_flexe_phy_lookup_by_inst(lchip, dp_id, asic_inst_id);
    if (!phy_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Asic inst %d not belong to any group!\n", asic_inst_id);
        return CTC_E_INVALID_PARAM;
    }

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);

    /* get instance id according to agreement */
    *p_instance_id = (CTC_PORT_SPEED_50G == speed_mode) ? asic_inst_id : (asic_inst_id / 2);

    /* get physical serdes id */
    logical_serdes_id = phy_node->logical_serdes_base;
    CTC_ERROR_RETURN(_sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, logical_serdes_id, p_serdes_id));
    SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == *p_serdes_id), CTC_E_INVALID_PARAM);

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_get_phy_oh_sync(uint8 lchip, uint8 serdes_id, uint32* p_enable)
{
    uint8 logical_serdes_id = 0;
    sys_flexe_group_t* group_node = NULL;

    if (!p_enable)
    {
        return CTC_E_NO_MEMORY;
    }

    CTC_ERROR_RETURN(_sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, (uint8)serdes_id, &logical_serdes_id));
    SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
    group_node = _sys_tmm_flexe_group_lookup_by_serdes(lchip, logical_serdes_id);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] SerDes ID %d is not used by any group\n", serdes_id);
        return CTC_E_NOT_EXIST;
    }

    CTC_ERROR_RETURN(_sys_tmm_flexe_get_cfgrxoh_sync(lchip, group_node, p_enable));

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_get_dp_asic_id(uint8 lchip, uint8 serdes_id, uint32 instance_id, uint8* p_dp_id, uint8 p_asic_inst_id[])
{
    uint8 logical_serdes_id = 0;
    sys_flexe_phy_t*   phy_node   = NULL;

    if (!p_dp_id || !p_asic_inst_id)
    {
        return CTC_E_NO_MEMORY;
    }

    /* get dp id */
    *p_dp_id = SYS_TMM_GET_DP_ID_FROM_SERDES(serdes_id);

    /* get phy node */
    _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, serdes_id, &logical_serdes_id);
    SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
    phy_node = _sys_tmm_flexe_get_phy_node(lchip, logical_serdes_id);
    if (!phy_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% [FlexE] SerDes ID %d is not used by any group\n", serdes_id);
        return CTC_E_INVALID_PARAM;
    }
    p_asic_inst_id[0] = phy_node->inst_base;
    p_asic_inst_id[1] = SYS_FLEXE_UNUSED_FLAG_U8;

    return CTC_E_NONE;
}


#define ____FlexE_ALARM____

int32
sys_tmm_flexe_alarm_phy_link_down(uint8 lchip, uint8 logical_serdes_id)
{
    uint8  gchip_id         = 0;
    uint32 gport            = 0;
    ctc_port_link_status_t     port_link_status;
    CTC_INTERRUPT_EVENT_FUNC   cb = NULL;
    sys_datapath_serdes_info_t* p_serdes  = NULL;

    /* get gchip_id and port_link_status */
    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip_id));
    CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, logical_serdes_id, &p_serdes));
    if (NULL != p_serdes)
    {
        gport = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip_id, p_serdes->lport);
        port_link_status.gport = gport;
    }

    /* cb */
    CTC_ERROR_RETURN(sys_usw_interrupt_get_event_cb(lchip, CTC_EVENT_PORT_LINK_CHANGE, &cb));
    if (cb)
    {
        cb(gchip_id, &port_link_status);
    }

    return CTC_E_NONE;
}

STATIC int32
sys_tmm_flexe_alarm_phy_link(uint8 lchip, sys_flexe_group_t *group_node, sys_flexe_phy_t* phy_node, uint8* p_gchip_id, uint8* p_event_action, uint32* p_gport)
{
    uint8 lock              = 0;
    uint8 mflock            = 0;
    uint8 padlock           = 0;
    uint8 rpf_clear         = 0;
    uint8 serdes_id         = 0;
    uint8 event_action      = SYS_FLEXE_EVENT_NONE;
    uint8 gchip_id          = 0;
    uint8 phy_link          = 1;
    uint8 pcs_link          = 0;
    uint32 gport            = 0;
    sys_datapath_serdes_info_t* p_serdes  = NULL;
    sys_datapath_lport_attr_t* port_attr = NULL;

    /* get p_serdes */
    CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, phy_node->logical_serdes_base, &p_serdes));
    if (!p_serdes)
    {
        return CTC_E_NONE;
    }
    /* get port_attr */
    CTC_ERROR_RETURN(sys_usw_mac_get_port_capability(lchip, p_serdes->lport, &port_attr));
    if (!port_attr)
    {
        return CTC_E_NONE;
    }

    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip_id));
    gport = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip_id, p_serdes->lport);

    /* check link_stat/rpf/lock */
    CTC_ERROR_RETURN(_sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, phy_node->logical_serdes_base, &serdes_id));
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_phy_status_by_lport(lchip, p_serdes->lport, port_attr, SYS_FLEXE_PCS_LINK, &pcs_link));
    if (!pcs_link)
    {
        phy_link = 0;
    }
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_phy_status_by_lport(lchip, p_serdes->lport, port_attr, SYS_FLEXE_OH_LOCK, &lock));
    if (!lock)
    {
        phy_link = 0;
    }
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_phy_status_by_lport(lchip, p_serdes->lport, port_attr, SYS_FLEXE_OHMF_LOCK, &mflock));
    if (!mflock)
    {
        phy_link = 0;
    }
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_phy_status_by_lport(lchip, p_serdes->lport, port_attr, SYS_FLEXE_PAD_LOCK, &padlock));
    if (!padlock)
    {
        phy_link = 0;
    }
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_phy_status_by_lport(lchip, p_serdes->lport, port_attr, SYS_FLEXE_RPF_CLEAR, &rpf_clear));
    if (!rpf_clear)
    {
        phy_link = 0;
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] %s @ %d, serdes id: %d, rpf_clear %d, oh_lock %d, oh_mflock %d, padlock %d, pcs_link %d\n", \
        __FUNCTION__, __LINE__, serdes_id, rpf_clear, lock, mflock, padlock, pcs_link);

    /* alarm process */
    if (phy_link)
    {
        event_action = SYS_FLEXE_EVENT_CLEAR;
    }
    else
    {
        event_action = SYS_FLEXE_EVENT_SET;
    }

    if (p_event_action)
    {
        *p_event_action = event_action;
    }
    if (p_gport)
    {
        *p_gport = gport;
    }
    if (p_gchip_id)
    {
        *p_gchip_id = gchip_id;
    }

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_alarm_lpf(uint8 lchip, uint8 logical_serdes_id, uint32 link_stat)
{
    uint8 physical_serdes_id = 0;
    uint8 event_action       = SYS_FLEXE_EVENT_NONE;
    ctc_flexe_status_event_t flexe_event;  /* LPF */
    ctc_flexe_status_event_t flexe_event1; /* RPF */
    sys_flexe_group_t *group_node = NULL;
    sys_flexe_phy_t* phy_node = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "[FlexE] %s @ %d, LPF interrupt isr, PHY id %d\n", \
        __FUNCTION__, __LINE__, logical_serdes_id);

    MAC_LOCK;

    sal_memset(&flexe_event, 0, sizeof(ctc_flexe_status_event_t));
    sal_memset(&flexe_event1, 0, sizeof(ctc_flexe_status_event_t));

    /* get group node */
    group_node = _sys_tmm_flexe_group_lookup_by_serdes(lchip, logical_serdes_id);
    if (!group_node)
    {
        MAC_UNLOCK;
        return CTC_E_NONE;
    }
    /* get phy node */
    phy_node = _sys_tmm_flexe_get_phy_node(lchip, logical_serdes_id);
    if (!phy_node)
    {
        MAC_UNLOCK;
        return CTC_E_NONE;
    }
    _sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, logical_serdes_id, &physical_serdes_id);

    if (!link_stat)
    {
        if (!CTC_IS_BIT_SET(phy_node->event_bmp, CTC_FLEXE_EVENT_LPF))
        {
            CTC_BIT_SET(phy_node->event_bmp, CTC_FLEXE_EVENT_LPF);
            event_action = SYS_FLEXE_EVENT_SET; 
        }
    }
    else
    {
        if (CTC_IS_BIT_SET(phy_node->event_bmp, CTC_FLEXE_EVENT_LPF))
        {
            CTC_BIT_UNSET(phy_node->event_bmp, CTC_FLEXE_EVENT_LPF);
            event_action = SYS_FLEXE_EVENT_CLEAR;
        }
    }

    if (SYS_FLEXE_EVENT_NONE != event_action)
    {
        /* LPF */
        flexe_event.flag = (SYS_FLEXE_EVENT_CLEAR == event_action) ? CTC_FLEXE_EVENT_FLAG_CLEAR : 0;
        flexe_event.event_type = CTC_FLEXE_EVENT_LPF;
        flexe_event.serdes_id = physical_serdes_id;
    }
    if (SYS_FLEXE_EVENT_SET == event_action)
    {
        /* RPF trigger */
        CTC_BIT_SET(phy_node->event_bmp, CTC_FLEXE_EVENT_RPF);
        flexe_event1.flag = 0;
        flexe_event1.event_type = CTC_FLEXE_EVENT_RPF;
        flexe_event1.serdes_id = physical_serdes_id;
        /* control rpf by software */
        if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A))
        {
            CTC_ERROR_RETURN_WITH_MAC_UNLOCK(_sys_tmm_flexe_set_phy_rpf_val(lchip, group_node->flexe_shim_id, phy_node, TRUE));
        }
    }

    MAC_UNLOCK;

    /* cb */
    if (SYS_FLEXE_EVENT_NONE != event_action)
    {
        _sys_tmm_flexe_intr_cb(lchip, &flexe_event);
    }
    if (SYS_FLEXE_EVENT_SET == event_action)
    {
        _sys_tmm_flexe_intr_cb(lchip, &flexe_event1);
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_alarm_client_mismatch(uint8 lchip, sys_flexe_client_t* client_node, uint8* p_event_action)
{
    int32 ret = 0;
    uint8 match = 1;
    uint8 event_action = SYS_FLEXE_EVENT_NONE;

    ret = sys_tmm_flexe_check_client_match(lchip, client_node, &match);
    if ((0 != ret) || !match)
    {
        match = 0;
    }

    if (!match)
    {
        if (!CTC_IS_BIT_SET(client_node->event_bmp, SYS_FLEXE_EVENT_CLIENT_MISMATCH))
        {
            CTC_BIT_SET(client_node->event_bmp, SYS_FLEXE_EVENT_CLIENT_MISMATCH);
            event_action = SYS_FLEXE_EVENT_SET;
        }
    }
    else
    {
        if (CTC_IS_BIT_SET(client_node->event_bmp, SYS_FLEXE_EVENT_CLIENT_MISMATCH))
        {
            CTC_BIT_UNSET(client_node->event_bmp, SYS_FLEXE_EVENT_CLIENT_MISMATCH);
            event_action = SYS_FLEXE_EVENT_CLEAR;
        }
    }

    if (p_event_action)
    {
        *p_event_action = event_action;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_alarm_mismatch(uint8 lchip, uint8 inst_id, uint8 flexe_shim_id)
{
    uint8 spi               = 0;
    uint8 serdes_id         = 0;
    uint8 speed_mode        = 0;
    uint8 event_action      = SYS_FLEXE_EVENT_NONE;
    uint32 i                = 0;
    uint32 flexe_map_flag   = 0;  /*0-match  1-mismatch */
    uint32 client_cal_flag  = 0;  /*0-match  1-mismatch */
    uint32 frame_id         = 0;
    uint32 frame_num        = 0;
    uint32 slot_num         = 0;
    uint32 inst_offset      = 0;
    uint32 rx_c             = 0;
    uint32 client_cal[SYS_FLEXE_MAX_INST_CNT][SYS_FLEXE_OH_MAX_SLOT_PER_INST] = {{0}};
    ctc_flexe_status_event_t flexe_event;
    sys_flexe_group_t* group_node = NULL;
    sys_flexe_phy_t* phy_node = NULL;
    sys_flexe_ohram_info_t*        p_ohram_info_rx = NULL;
    sys_flexe_ohram_info_t*        p_ohram_info_tx = NULL;
    int32 ret = CTC_E_NONE;

    p_ohram_info_rx = (sys_flexe_ohram_info_t*)mem_malloc(MEM_DMPS_MODULE, sizeof(sys_flexe_ohram_info_t));
    if(NULL == p_ohram_info_rx)
    {
        goto DONE;
    }
    sal_memset(p_ohram_info_rx, 0, sizeof(sys_flexe_ohram_info_t));
    p_ohram_info_tx = (sys_flexe_ohram_info_t*)mem_malloc(MEM_DMPS_MODULE, sizeof(sys_flexe_ohram_info_t));
    if(NULL == p_ohram_info_tx)
    {
        goto DONE;
    }
    sal_memset(p_ohram_info_tx, 0, sizeof(sys_flexe_ohram_info_t));

    group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, flexe_shim_id, inst_id);
    if (!group_node)
    {
        ret = CTC_E_NONE;
        goto DONE;
    }

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);

    if (CTC_PORT_SPEED_50G != speed_mode)
    {
        frame_num = SYS_FLEXE_OH_FRAME_NUM;
        slot_num = SYS_FLEXE_OH_MAX_SLOT_PER_INST;
    }
    else
    {
        frame_num = SYS_FLEXE_OH_FRAME_NUM_50G;
        slot_num = MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST);
    }

    /* read rx ohram */
    ret = _sys_tmm_flexe_parse_ohram(lchip, group_node, inst_id, p_ohram_info_rx, SYS_FLEXE_DIR_RX);
    if (ret != 0)
    {
        ret = CTC_E_NONE;
        goto DONE;
    }
    ret = _sys_tmm_flexe_parse_ohram(lchip, group_node, inst_id, p_ohram_info_tx, SYS_FLEXE_DIR_TX);
    if (ret != 0)
    {
        ret = CTC_E_NONE;
        goto DONE;
    }

    /* search serdes_id */
    phy_node = _sys_tmm_flexe_phy_lookup_by_inst(lchip, group_node->flexe_shim_id, inst_id);
    if (!phy_node)
    {
        ret = CTC_E_NONE;
        goto DONE;
    }
    ret = _sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, phy_node->logical_serdes_base, &serdes_id);
    if (ret != 0)
    {
        ret = CTC_E_NONE;
        goto DONE;
    }

    /* calculate instance offset */
    ret = _sys_tmm_flexe_get_phy_instance_offset(lchip, phy_node, inst_id, &inst_offset);
    if (ret != 0)
    {
        ret = CTC_E_NONE;
        goto DONE;
    }

    /* 1. group_number */
    if (group_node->group_number != p_ohram_info_rx->group_num)
    {
        if (CTC_IS_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_GRP_NUM_MISMATCH))
        {
            if (phy_node->remote_state[inst_offset].group_num != p_ohram_info_rx->group_num)
            {
                event_action = SYS_FLEXE_EVENT_SET;
            }
        }
        else
        {
            CTC_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_GRP_NUM_MISMATCH);
            event_action = SYS_FLEXE_EVENT_SET;
        }
    }
    else
    {
        if (CTC_IS_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_GRP_NUM_MISMATCH))
        {
            CTC_BIT_UNSET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_GRP_NUM_MISMATCH);
            event_action = SYS_FLEXE_EVENT_CLEAR;
        }
    }
    if (SYS_FLEXE_EVENT_NONE != event_action)
    {
        sal_memset(&flexe_event, 0, sizeof(ctc_flexe_status_event_t));
        flexe_event.flag = (SYS_FLEXE_EVENT_CLEAR == event_action) ? CTC_FLEXE_EVENT_FLAG_CLEAR : 0;
        flexe_event.event_type = CTC_FLEXE_EVENT_GRP_NUM_MISMATCH;
        flexe_event.serdes_id = serdes_id;
        flexe_event.instance_offset = inst_offset;
        _sys_tmm_flexe_fill_event(lchip, flexe_shim_id, inst_id, &flexe_event);
        _sys_tmm_flexe_intr_cb(lchip, &flexe_event);
    } 

    /* 2. instance number */
    event_action = SYS_FLEXE_EVENT_NONE;
    if (p_ohram_info_tx->inst_num != p_ohram_info_rx->inst_num)
    {
        if (CTC_IS_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_INST_NUM_MISMATCH))
        {
            if (phy_node->remote_state[inst_offset].instance_num!= p_ohram_info_rx->inst_num)
            {
                event_action = SYS_FLEXE_EVENT_SET;
            }
        }
        else
        {
            CTC_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_INST_NUM_MISMATCH);
            event_action = SYS_FLEXE_EVENT_SET;
        }
    }
    else
    {
        if (CTC_IS_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_INST_NUM_MISMATCH))
        {
            CTC_BIT_UNSET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_INST_NUM_MISMATCH);
            event_action = SYS_FLEXE_EVENT_CLEAR;
        }
    }
    if (SYS_FLEXE_EVENT_NONE != event_action)
    {
        sal_memset(&flexe_event, 0, sizeof(ctc_flexe_status_event_t));
        flexe_event.flag = (SYS_FLEXE_EVENT_CLEAR == event_action) ? CTC_FLEXE_EVENT_FLAG_CLEAR : 0;
        flexe_event.event_type = CTC_FLEXE_EVENT_INST_NUM_MISMATCH;
        flexe_event.serdes_id = serdes_id;
        flexe_event.instance_offset = inst_offset;
        _sys_tmm_flexe_fill_event(lchip, flexe_shim_id, inst_id, &flexe_event);
        _sys_tmm_flexe_intr_cb(lchip, &flexe_event);
    }

    /* 3. flexe_map */
    event_action = SYS_FLEXE_EVENT_NONE;
    for (frame_id = 0; frame_id < frame_num; frame_id++)
    {
        if (p_ohram_info_tx->flexe_map[frame_id] != p_ohram_info_rx->flexe_map[frame_id])
        {
            flexe_map_flag = 1;
            break;
        }
    }
    if (1 == flexe_map_flag)
    {
        if (CTC_IS_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_MAP_MISMATCH))
        {
            for (i = 0; i < frame_num; i++)
            {
                if (phy_node->remote_state[inst_offset].flexe_map[i] != p_ohram_info_rx->flexe_map[i])
                {
                    event_action = SYS_FLEXE_EVENT_SET;
                    break;
                }
            }
        }
        else
        {
            CTC_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_MAP_MISMATCH);
            event_action = SYS_FLEXE_EVENT_SET;
        }
    }
    else
    {
        if (CTC_IS_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_MAP_MISMATCH))
        {
            CTC_BIT_UNSET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_MAP_MISMATCH);
            event_action = SYS_FLEXE_EVENT_CLEAR;
        }
    }
    if (SYS_FLEXE_EVENT_NONE != event_action)
    {
        sal_memset(&flexe_event, 0, sizeof(ctc_flexe_status_event_t));
        flexe_event.flag = (SYS_FLEXE_EVENT_CLEAR == event_action) ? CTC_FLEXE_EVENT_FLAG_CLEAR : 0;
        flexe_event.event_type = CTC_FLEXE_EVENT_MAP_MISMATCH;
        flexe_event.serdes_id = serdes_id;
        flexe_event.instance_offset = inst_offset;
        _sys_tmm_flexe_fill_event(lchip, flexe_shim_id, inst_id, &flexe_event);
        _sys_tmm_flexe_intr_cb(lchip, &flexe_event);
    }

    /* 4 client calendar */
    /* just for static mode */
    if (p_ohram_info_rx->c0 + p_ohram_info_rx->c1 + p_ohram_info_rx->c2 <= 1) /* '0' at most */
    {
        rx_c = 0;
    }
    else
    {
        rx_c = 1;
    }
    event_action = SYS_FLEXE_EVENT_NONE;
    ret = _sys_tmm_flexe_get_group_client_cal(lchip, group_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_ACTIVE_FLAG, client_cal);
    if (ret != 0)
    {
        ret = CTC_E_NONE;
        goto DONE;
    }
    if (0 == rx_c)
    {
        for (spi = 0; spi < slot_num; spi++)
        {
            if(client_cal[inst_id][spi] != p_ohram_info_rx->inst_client_map[inst_id][spi])
            {
                client_cal_flag = 1;
            }
        }
    }
    else
    {
        for (spi = 0; spi < slot_num; spi++)
        {
            if(client_cal[inst_id][spi] != p_ohram_info_rx->inst_client_map_b[inst_id][spi])
            {
                client_cal_flag = 1;
            }
        }
    }
    if ((SYS_FLEXE_DYNAMIC_NEGO_SWITCH == group_node->switch_mode) && (SYS_FLEXE_GROUP_RX_IDLE != group_node->rx.crac_state))
    {
        client_cal_flag = 0;
    }

    if (1 == client_cal_flag)
    {
        if (CTC_IS_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_CAL_MISMATCH))
        {
            for (spi = 0; spi < slot_num; spi++)
            {
                if(phy_node->remote_state[inst_offset].client_map[spi] != p_ohram_info_rx->inst_client_map[inst_id][spi]\
                    || phy_node->remote_state[inst_offset].client_map_b[spi] != p_ohram_info_rx->inst_client_map_b[inst_id][spi])
                {
                    event_action = SYS_FLEXE_EVENT_SET;
                    break;
                }
            }
        }
        else
        {
            CTC_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_CAL_MISMATCH);
            event_action = SYS_FLEXE_EVENT_SET;
        }
    }
    else
    {
        if (CTC_IS_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_CAL_MISMATCH))
        {
            CTC_BIT_UNSET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_CAL_MISMATCH);
            event_action = SYS_FLEXE_EVENT_CLEAR;
        }
    }
    if (SYS_FLEXE_EVENT_NONE != event_action)
    {
        sal_memset(&flexe_event, 0, sizeof(ctc_flexe_status_event_t));
        flexe_event.flag = (SYS_FLEXE_EVENT_CLEAR == event_action) ? CTC_FLEXE_EVENT_FLAG_CLEAR : 0;
        flexe_event.event_type = CTC_FLEXE_EVENT_CAL_MISMATCH;
        flexe_event.serdes_id = serdes_id;
        flexe_event.instance_offset = inst_offset;
        _sys_tmm_flexe_fill_event(lchip, flexe_shim_id, inst_id, &flexe_event);
        _sys_tmm_flexe_intr_cb(lchip, &flexe_event);
    }

    /* update current status in soft table */
    phy_node->remote_state[inst_offset].inst_offset = inst_offset;
    phy_node->remote_state[inst_offset].group_num = p_ohram_info_rx->group_num;
    phy_node->remote_state[inst_offset].instance_num = p_ohram_info_rx->inst_num;
    for (i = 0; i < CTC_FLEXE_OH_MF_NUM; i++)
    {
        phy_node->remote_state[inst_offset].flexe_map[i] = 0;
        if (i < frame_num)
        {
            phy_node->remote_state[inst_offset].flexe_map[i] = p_ohram_info_rx->flexe_map[i];
        }
    }
    for (i = 0; i < SYS_FLEXE_OH_MAX_SLOT_PER_INST; i++)
    {
        phy_node->remote_state[inst_offset].client_map[i] = 0;
        phy_node->remote_state[inst_offset].client_map_b[i] = 0;
        if (i < slot_num)
        {
            phy_node->remote_state[inst_offset].client_map[i] = p_ohram_info_rx->inst_client_map[inst_id][i];
            phy_node->remote_state[inst_offset].client_map_b[i] = p_ohram_info_rx->inst_client_map_b[inst_id][i];
        }
    }

DONE:
    if (p_ohram_info_rx) mem_free(p_ohram_info_rx);
    if (p_ohram_info_tx) mem_free(p_ohram_info_tx);

    return ret;
}

STATIC int32
_sys_tmm_flexe_alarm_crcerr(uint8 lchip, uint8 inst_id, uint8 flexe_shim_id, uint8 *p_crc_error)
{
    uint8 crc_error         = 0;    /*1-crc_error  0-no crc_error */
    uint8 serdes_id         = 0;
    uint8 event_action      = SYS_FLEXE_EVENT_NONE;
    uint8 unmask           = 0;
    uint32 crc_cnt          = 0;
    uint32 inst_offset      = 0;
    int32 ret               = CTC_E_NONE;
    ctc_flexe_status_event_t flexe_event;
    sys_flexe_group_t* group_node = NULL;
    sys_flexe_phy_t* phy_node = NULL;

    sal_memset(&flexe_event, 0, sizeof(ctc_flexe_status_event_t));

    group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, flexe_shim_id, inst_id);
    if (!group_node)
    {
        return CTC_E_NONE;
    }
    flexe_shim_id = group_node->flexe_shim_id;

    /* check whether already do port-en */
    ret = _sys_tmm_flexe_check_group_ohlock_unmask(lchip, group_node, &unmask);
    if ((ret != 0) || (0 == unmask))
    {
        return CTC_E_NONE;
    }

    /* search serdes_id */
    phy_node = _sys_tmm_flexe_phy_lookup_by_inst(lchip, group_node->flexe_shim_id, inst_id);
    if (!phy_node)
    {
        return CTC_E_NONE;
    }
    ret = _sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, phy_node->logical_serdes_base, &serdes_id);
    if (ret != 0)
    {
        return CTC_E_NONE;
    }

    /* calculate instance offset */
    ret = _sys_tmm_flexe_get_phy_instance_offset(lchip, phy_node, inst_id, &inst_offset);
    if (ret != 0)
    {
        return CTC_E_NONE;
    }

    /* check crcErr count */
    ret =_sys_tmm_flexe_get_crcerr(lchip, flexe_shim_id, inst_id, &crc_cnt);
    if (ret != 0)
    {
        return CTC_E_NONE;
    }
    if(crc_cnt)
    {
        crc_error = 1;
        phy_node->crc_cnt += crc_cnt;
    }

    /* alarm */
    event_action = SYS_FLEXE_EVENT_NONE;
    if (crc_error)
    {
        if (CTC_IS_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_CRC_ERR))
        {
            event_action = SYS_FLEXE_EVENT_SET;
        }
        else
        {
            CTC_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_CRC_ERR);
            event_action = SYS_FLEXE_EVENT_SET;
        }
    }
    else
    {
        if (CTC_IS_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_CRC_ERR))
        {
            CTC_BIT_UNSET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_CRC_ERR);
            event_action = SYS_FLEXE_EVENT_CLEAR;
        }
    }
    if (SYS_FLEXE_EVENT_NONE != event_action)
    {
        flexe_event.flag = (SYS_FLEXE_EVENT_CLEAR == event_action) ? CTC_FLEXE_EVENT_FLAG_CLEAR : 0;
        flexe_event.event_type = CTC_FLEXE_EVENT_CRC_ERR;
        flexe_event.instance_offset= inst_offset;
        flexe_event.serdes_id = serdes_id;
        _sys_tmm_flexe_intr_cb(lchip, &flexe_event);
    }

    /* update current status in soft table */
    phy_node->remote_state[inst_offset].inst_offset = inst_offset;

    return ret;
}

STATIC int32
_sys_tmm_flexe_alarm_deskew(uint8 lchip, sys_flexe_group_t *group_node)
{
    uint8 i                 = 0;
    uint8 inst_id           = 0;
    uint8 phy_skew_flag     = 0;  /* 0:do nothing  1:alarm */
    int32 ret               = CTC_E_NONE;
    uint8 event_action      = SYS_FLEXE_EVENT_NONE;
    ctc_flexe_status_event_t flexe_event;

    sal_memset(&flexe_event, 0, sizeof(ctc_flexe_status_event_t));

    /* check whether there is only one phy in the group */
    if (1 == group_node->phy_cnt)
    {
        return CTC_E_NONE;
    }

    /* check each instance's deskewOverflow in the group */
    ret =_sys_tmm_flexe_get_group_deskew(lchip, group_node, &phy_skew_flag);
    if (ret != 0)
    {
        return CTC_E_NONE;
    }

    /* alarm */
    event_action = SYS_FLEXE_EVENT_NONE;
    if (1 == phy_skew_flag)
    {
        if (!CTC_IS_BIT_SET(group_node->event_bmp, CTC_FLEXE_EVENT_GROUP_DESKEW_OVER))
        {
            CTC_BIT_SET(group_node->event_bmp, CTC_FLEXE_EVENT_GROUP_DESKEW_OVER);
            event_action = SYS_FLEXE_EVENT_SET;
        }
        for (i = 0; i < group_node->inst_cnt; i++)
        {
            inst_id = group_node->inst_list[i];
            ret = _sys_tmm_flexe_clear_inst_ohlock(lchip, group_node->flexe_shim_id, inst_id);
            if (ret != 0)
            {
                return CTC_E_NONE;
            }
        }
    }
    else
    {
        if (CTC_IS_BIT_SET(group_node->event_bmp, CTC_FLEXE_EVENT_GROUP_DESKEW_OVER))
        {
            CTC_BIT_UNSET(group_node->event_bmp, CTC_FLEXE_EVENT_GROUP_DESKEW_OVER);
            event_action = SYS_FLEXE_EVENT_CLEAR;
        }
    }
    if (SYS_FLEXE_EVENT_NONE != event_action)
    {
        flexe_event.flag = (SYS_FLEXE_EVENT_CLEAR == event_action) ? CTC_FLEXE_EVENT_FLAG_CLEAR : 0;
        flexe_event.event_type = CTC_FLEXE_EVENT_GROUP_DESKEW_OVER;
        flexe_event.group_num = group_node->group_number;
        _sys_tmm_flexe_intr_cb(lchip, &flexe_event);
    }

    return CTC_E_NONE;
}

STATIC int32 
_sys_tmm_flexe_alarm_rpf_isr(uint8 lchip, uint32 flexe_shim_id, uint8 asic_inst, uint8 intr)
{
    /* intr: falling:0, rising:1 */
    uint8 rpf               = 0;
    uint8 serdes_id         = 0;
    uint8 gchip_id          = 0;
    uint8 unmask            = 0;    /*1-done unmask  0-not done unmask */
    uint8 event_action      = SYS_FLEXE_EVENT_NONE;
    uint8 event_action_phy  = SYS_FLEXE_EVENT_NONE;
    uint32 gport            = 0;
    sys_flexe_phy_t* phy_node = NULL;
    sys_flexe_group_t* group_node = NULL;
    ctc_flexe_status_event_t flexe_event;
    ctc_port_link_status_t     port_link_status;
    CTC_INTERRUPT_EVENT_FUNC   cb = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] %s @ %d, RPF interrupt isr, flexe_shim_id %d, asic_inst %d, intr 0x%x\n", \
        __FUNCTION__, __LINE__, flexe_shim_id, asic_inst, intr);

    MAC_LOCK;

    sal_memset(&flexe_event, 0, sizeof(ctc_flexe_status_event_t));

    /* get group_node from asic_inst id */
    group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, flexe_shim_id, asic_inst);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] ASIC inst %d not belong to any group, skip!\n", asic_inst);
        MAC_UNLOCK;
        return CTC_E_NONE;
    }

    /* get phy_node from asic_inst id */
    phy_node = _sys_tmm_flexe_phy_lookup_by_inst(lchip, flexe_shim_id, asic_inst);
    if (!phy_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] ASIC inst %d not belong to any phy, skip!\n", asic_inst);
        MAC_UNLOCK;
        return CTC_E_NONE;
    }
    CTC_ERROR_RETURN_WITH_MAC_UNLOCK(_sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, phy_node->logical_serdes_base, &serdes_id));

    /* check whether already do port-en */
    CTC_ERROR_RETURN_WITH_MAC_UNLOCK(_sys_tmm_flexe_check_phy_ohlock_unmask(lchip, group_node, phy_node->logical_serdes_base, &unmask));
    if (0 == unmask && !intr)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] serdes %d not do port-en, skip!\n", serdes_id);
        MAC_UNLOCK;
        return CTC_E_NONE;
    }

    /* check whether intr is same with register */
    CTC_ERROR_RETURN_WITH_MAC_UNLOCK(_sys_tmm_flexe_clear_inst_ohlock(lchip, flexe_shim_id, phy_node->inst_base));
    sal_task_sleep(5);
    CTC_ERROR_RETURN_WITH_MAC_UNLOCK(_sys_tmm_flexe_get_inst_rpf(lchip, group_node->flexe_shim_id, phy_node->inst_base, &rpf));
    if (intr != rpf)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] ASIC inst %d intr %d is conflict with register %d, use register value!\n", \
            asic_inst, intr, rpf);
        intr = rpf;
    }

    /* for debug */
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] %s @ %d, RPF basic check pass, flexe_shim_id: %d asic_inst: %d oh_intr: %d\n",__FUNCTION__, __LINE__, flexe_shim_id, asic_inst, intr);

    /* alarm */
    if (intr)
    {
        if (!CTC_IS_BIT_SET(phy_node->event_bmp, CTC_FLEXE_EVENT_RPF))
        {
            CTC_BIT_SET(phy_node->event_bmp, CTC_FLEXE_EVENT_RPF);
            event_action = SYS_FLEXE_EVENT_SET;
        }
    }
    else
    {
        if (CTC_IS_BIT_SET(phy_node->event_bmp, CTC_FLEXE_EVENT_RPF))
        {
            CTC_BIT_UNSET(phy_node->event_bmp, CTC_FLEXE_EVENT_RPF);
            event_action = SYS_FLEXE_EVENT_CLEAR;
        }
    }

    if (SYS_FLEXE_EVENT_NONE != event_action)
    {
        flexe_event.flag = (SYS_FLEXE_EVENT_CLEAR == event_action) ? CTC_FLEXE_EVENT_FLAG_CLEAR : 0;
        flexe_event.event_type = CTC_FLEXE_EVENT_RPF;
        flexe_event.serdes_id = serdes_id;
    }

    /* phy linkup process */
    CTC_ERROR_RETURN_WITH_MAC_UNLOCK(sys_tmm_flexe_alarm_phy_link(lchip, group_node, phy_node, &gchip_id, &event_action_phy, &gport));
    port_link_status.gport = gport;

    MAC_UNLOCK;

    if (SYS_FLEXE_EVENT_NONE != event_action)
    {
        _sys_tmm_flexe_intr_cb(lchip, &flexe_event);
    }
    if (SYS_FLEXE_EVENT_NONE != event_action_phy)
    {
        CTC_ERROR_RETURN(sys_usw_interrupt_get_event_cb(lchip, CTC_EVENT_PORT_LINK_CHANGE, &cb));
        if (cb)
        {
            cb(gchip_id, &port_link_status);
        }
    }

    return CTC_E_NONE;
}

int32 
_sys_tmm_flexe_alarm_ohlock_ohmflock_isr(uint8 lchip, uint32 flexe_shim_id, uint8 asic_inst, uint8 intr, uint8 event_type)
{
    uint8 lock              = 0;
    uint8 serdes_id         = 0;
    uint8 speed_mode        = 0;
    uint8 unmask            = 0;    /*1-done unmask  0-not done unmask */
    uint8 gchip_id          = 0;
    uint8 event_action      = SYS_FLEXE_EVENT_NONE;
    uint8 event_action_phy  = SYS_FLEXE_EVENT_NONE;
    uint32 gport            = 0;
    ctc_port_link_status_t     port_link_status;
    ctc_flexe_status_event_t flexe_event;
    sys_flexe_phy_t* phy_node = NULL;
    sys_flexe_group_t* group_node = NULL;
    CTC_INTERRUPT_EVENT_FUNC   cb = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    MAC_LOCK;

    if (CTC_FLEXE_EVENT_LOF == event_type)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO]  %s @ %d, OHLock interrupt isr, flexe_shim_id %d, asic_inst %d, oh_intr 0x%x\n", \
            __FUNCTION__, __LINE__, flexe_shim_id, asic_inst, intr);
    }
    else if (CTC_FLEXE_EVENT_LOMF == event_type)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO]  %s @ %d, OHMFLock interrupt isr, flexe_shim_id %d, asic_inst %d, ohmf_intr 0x%x\n", \
            __FUNCTION__, __LINE__, flexe_shim_id, asic_inst, intr);
    }

    sal_memset(&flexe_event, 0, sizeof(ctc_flexe_status_event_t));

    /* get group_node from asic_inst id */
    group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, flexe_shim_id, asic_inst);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO]  ASIC inst %d not belong to any group, skip!\n", asic_inst);
        MAC_UNLOCK;
        return CTC_E_NONE;
    }

    /* get phy_node from asic_inst id */
    phy_node = _sys_tmm_flexe_phy_lookup_by_inst(lchip, flexe_shim_id, asic_inst);
    if (!phy_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO]  ASIC inst %d not belong to any phy, skip!\n", asic_inst);
        MAC_UNLOCK;
        return CTC_E_NONE;
    }
    CTC_ERROR_RETURN_WITH_MAC_UNLOCK(_sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, phy_node->logical_serdes_base, &serdes_id));

    /* check whether asic_inst is first in the user instance */
    CTC_ERROR_RETURN_WITH_MAC_UNLOCK(_sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode));
    if((CTC_PORT_SPEED_50G != speed_mode) && (asic_inst%2))
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO]  ASIC inst %d is not first in the user instance, skip!\n", asic_inst);
        MAC_UNLOCK;
        return CTC_E_NONE;
    }

    /* check whether already do port-en */
    CTC_ERROR_RETURN_WITH_MAC_UNLOCK(_sys_tmm_flexe_check_phy_ohlock_unmask(lchip, group_node, phy_node->logical_serdes_base, &unmask));
    if (0 == unmask && !intr)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO] serdes %d not do port-en, skip!\n", serdes_id);
        MAC_UNLOCK;
        return CTC_E_NONE;
    }

    /* check whether intr is same with register */
    sal_task_sleep(2);
    if (CTC_FLEXE_EVENT_LOF == event_type)
    {
        _sys_tmm_flexe_get_inst_ohlock(lchip, flexe_shim_id, asic_inst, &lock);
    }
    else if (CTC_FLEXE_EVENT_LOMF == event_type)
    {
        _sys_tmm_flexe_get_inst_ohmflock(lchip, flexe_shim_id, asic_inst, &lock);
    }
    else
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO]  not support event_type!\n");
        MAC_UNLOCK;
        return CTC_E_NONE;
    }
    if (intr != lock)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO]  ASIC inst %d intr %d is conflict with register %d, use register value!\n", asic_inst, intr, lock);
        intr = lock;
    }

    /* for debug */
    if (CTC_FLEXE_EVENT_LOF == event_type)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO]  %s @ %d, OHLock basic check pass, flexe_shim_id: %d asic_inst: %d oh_intr: %d\n",__FUNCTION__, __LINE__, flexe_shim_id, asic_inst, intr);
    }
    else if (CTC_FLEXE_EVENT_LOMF == event_type)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FLEXE-INFO]  %s @ %d, OHMFLock basic check pass, flexe_shim_id: %d asic_inst: %d ohmf_intr: %d\n",__FUNCTION__, __LINE__, flexe_shim_id, asic_inst, intr);
    }

    /* alarm */
    if (!intr)
    {
        if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A) && (CTC_FLEXE_EVENT_LOF == event_type))
        {
            CTC_ERROR_RETURN_WITH_MAC_UNLOCK(_sys_tmm_flexe_set_phy_rpf_val(lchip, flexe_shim_id, phy_node, TRUE));
        }
        if (!CTC_IS_BIT_SET(phy_node->event_bmp, event_type))
        {
            CTC_BIT_SET(phy_node->event_bmp, event_type);
            event_action = SYS_FLEXE_EVENT_SET; 
        }
    }
    else
    {
        if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A) && (CTC_FLEXE_EVENT_LOF == event_type))
        {
            CTC_ERROR_RETURN_WITH_MAC_UNLOCK(_sys_tmm_flexe_set_phy_rpf_val(lchip, flexe_shim_id, phy_node, FALSE));
        }
        if (CTC_IS_BIT_SET(phy_node->event_bmp, event_type))
        {
            CTC_BIT_UNSET(phy_node->event_bmp, event_type);
            event_action = SYS_FLEXE_EVENT_CLEAR;
        }
    }
    if (SYS_FLEXE_EVENT_NONE != event_action)
    {
        flexe_event.flag = (SYS_FLEXE_EVENT_CLEAR == event_action) ? CTC_FLEXE_EVENT_FLAG_CLEAR : 0;
        flexe_event.event_type = event_type;
        flexe_event.serdes_id = serdes_id;
    }

    /* phy linkup process */
    CTC_ERROR_RETURN_WITH_MAC_UNLOCK(sys_tmm_flexe_alarm_phy_link(lchip, group_node, phy_node, &gchip_id, &event_action_phy, &gport));
    port_link_status.gport = gport;

    MAC_UNLOCK;

    if (SYS_FLEXE_EVENT_NONE != event_action)
    {
        _sys_tmm_flexe_intr_cb(lchip, &flexe_event);
    }
    if (SYS_FLEXE_EVENT_NONE != event_action_phy)
    {
        CTC_ERROR_RETURN(sys_usw_interrupt_get_event_cb(lchip, CTC_EVENT_PORT_LINK_CHANGE, &cb));
        if (cb)
        {
            cb(gchip_id, &port_link_status);
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_flexe_alarm_cr_timeout(uint8 lchip, uint32 group_id, uint8 cr_timeout)
{
    uint8 event_action = SYS_FLEXE_EVENT_NONE;
    sys_flexe_group_t* group_node = NULL;
    ctc_flexe_status_event_t flexe_event;

    sal_memset(&flexe_event, 0, sizeof(ctc_flexe_status_event_t));

    _sys_tmm_flexe_group_lookup(lchip, group_id, &group_node);
    if (!group_node)
    {
        return CTC_E_NONE;
    }

    /* alarm */
    if (1 == cr_timeout)    ///*1-timeout  0-not timeout*/
    {
        if (!CTC_IS_BIT_SET(group_node->event_bmp, CTC_FLEXE_EVENT_GROUP_CR_TIMEOUT))
        {
            CTC_BIT_SET(group_node->event_bmp, CTC_FLEXE_EVENT_GROUP_CR_TIMEOUT);
            event_action = SYS_FLEXE_EVENT_SET;
        }
    }
    else
    {
        if (CTC_IS_BIT_SET(group_node->event_bmp, CTC_FLEXE_EVENT_GROUP_CR_TIMEOUT))
        {
            CTC_BIT_UNSET(group_node->event_bmp, CTC_FLEXE_EVENT_GROUP_CR_TIMEOUT);
            event_action = SYS_FLEXE_EVENT_CLEAR;
        }
    }
    if (SYS_FLEXE_EVENT_NONE != event_action)
    {
        flexe_event.flag = (SYS_FLEXE_EVENT_CLEAR == event_action) ? CTC_FLEXE_EVENT_FLAG_CLEAR : 0;
        flexe_event.event_type = CTC_FLEXE_EVENT_GROUP_CR_TIMEOUT;
        flexe_event.group_num = group_node->group_number;
        _sys_tmm_flexe_intr_cb(lchip, &flexe_event);
    }

    return CTC_E_NONE;
}

#define  ____FLEXE_THREAD____

int32
sys_tmm_flexe_monitor(uint8 lchip)
{
    uint8 inst_id           = 0;
    uint8 flexe_shim_id     = 0;
    uint8 link_stat         = 1;    /*1-up  0-down*/
    uint8 ohlock            = 1;    /*1-LOCK  0-UNLOCK */
    uint8 ohmflock          = 1;    /*1-LOCK  0-UNLOCK */
    sys_flexe_group_t* tmp_group_node = NULL;

    /* poll every instance */
    for (flexe_shim_id = 0; flexe_shim_id < TMM_MAX_FLEXE_SHIM_CNT; flexe_shim_id++)
    {
        for (inst_id = 0; inst_id < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); inst_id++)
        {
            MAC_LOCK;
            /* get group_node from inst id */
            tmp_group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, flexe_shim_id, inst_id);
            if (!tmp_group_node)
            {
                MAC_UNLOCK;
                continue;
            }

            /* check switch_mode */
            if (1 == tmp_group_node->switch_mode)
            {
                MAC_UNLOCK;
                continue;
            }

            /* check first instance */
            if (inst_id != tmp_group_node->inst_list[0])
            {
                MAC_UNLOCK;
                continue;
            }

            /* check pcs up */
            _sys_tmm_flexe_check_group_phy_up(lchip, tmp_group_node, &link_stat);
            if (0 == link_stat)
            {
                MAC_UNLOCK;
                continue;
            }

            /* check ohlock */
            _sys_tmm_flexe_check_group_ohlock(lchip, tmp_group_node, &ohlock);
            if (0 == ohlock)
            {
                MAC_UNLOCK;
                continue;
            }

            /* check ohmflock */
            _sys_tmm_flexe_check_group_ohmflock(lchip, tmp_group_node, &ohmflock);
            if (0 == ohmflock)
            {
                MAC_UNLOCK;
                continue;
            }

            /* now group/instance all legal, start rx process */
            _sys_tmm_flexe_rx_ca_process(lchip, tmp_group_node);
            _sys_tmm_flexe_rx_cr_c_process(lchip, tmp_group_node);
            MAC_UNLOCK;
        }
    }

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_monitor_alarm(uint8 lchip)
{
    uint8 i                             = 0;
    uint8 inst_id                       = 0;
    uint8 flexe_shim_id                 = 0;
    uint8 link_stat                     = 1;    /*1-up  0-down*/
    uint8 crc_error                     = 0;    /*1-crc_error  0-no crc_error */
    uint8 ohlock                        = 1;    /*1-LOCK  0-UNLOCK */
    uint8 ohmflock                      = 1;    /*1-LOCK  0-UNLOCK */
    uint8 unmask                        = 0;    /*1-done unmask  0-not done unmask */
    uint8 speed_mode                    = 0;
    uint8 gchip_id                      = 0;
    uint8 event_action                  = SYS_FLEXE_EVENT_NONE;    
    CTC_INTERRUPT_EVENT_FUNC cb         = NULL;
    sys_flexe_group_t* tmp_group_node   = NULL;
    ctc_slistnode_t* node               = NULL;
    sys_flexe_client_t* tmp_client_node = NULL;
    ctc_flexe_link_event_t client_link_status;

    /* poll every instance */
    for (flexe_shim_id = 0; flexe_shim_id < TMM_MAX_FLEXE_SHIM_CNT; flexe_shim_id++)
    {
        for (inst_id = 0; inst_id < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); inst_id++)
        {
            MAC_LOCK;
            /* get group_node from inst id */
            tmp_group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, flexe_shim_id, inst_id);
            if (!tmp_group_node)
            {
                MAC_UNLOCK;
                continue;
            }

            _sys_tmm_flexe_check_group_phy_up(lchip, tmp_group_node, &link_stat);
            if (0 == link_stat)
            {
                MAC_UNLOCK;
                continue;
            }

            _sys_tmm_flexe_check_group_ohlock(lchip, tmp_group_node, &ohlock);
            if (0 == ohlock)
            {
                MAC_UNLOCK;
                continue;
            }

            _sys_tmm_flexe_check_group_ohmflock(lchip, tmp_group_node, &ohmflock);
            if (0 == ohmflock)
            {
                MAC_UNLOCK;
                continue;
            }

            _sys_tmm_flexe_get_group_phy_speed(lchip, tmp_group_node, &speed_mode);
            if (((CTC_PORT_SPEED_50G != speed_mode) && (0 == inst_id%2)) || (CTC_PORT_SPEED_50G == speed_mode))
            {
                _sys_tmm_flexe_alarm_crcerr(lchip, inst_id, flexe_shim_id, &crc_error);
                SYS_CONDITION_CONTINUE(crc_error);

                _sys_tmm_flexe_alarm_mismatch(lchip, inst_id, flexe_shim_id);
            }
            MAC_UNLOCK;
        }
    }

    MAC_LOCK;

    tmp_group_node = NULL;
    /* poll every group */
    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->group_list, node)
    {
        tmp_group_node = _ctc_container_of(node, sys_flexe_group_t, head);
        SYS_CONDITION_CONTINUE(!tmp_group_node || !tmp_group_node->phy_cnt);

        _sys_tmm_flexe_check_group_phy_up(lchip, tmp_group_node, &link_stat);
        SYS_CONDITION_CONTINUE(0 == link_stat);

        _sys_tmm_flexe_check_group_ohlock(lchip, tmp_group_node, &ohlock);
        SYS_CONDITION_CONTINUE(0 == ohlock);

        _sys_tmm_flexe_check_group_ohmflock(lchip, tmp_group_node, &ohmflock);
        SYS_CONDITION_CONTINUE(0 == ohmflock);

        _sys_tmm_flexe_check_group_ohlock_unmask(lchip, tmp_group_node, &unmask);
        SYS_CONDITION_CONTINUE(0 == unmask);

        _sys_tmm_flexe_alarm_deskew(lchip, tmp_group_node);
    }

    MAC_UNLOCK;

    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip_id));
    for (flexe_shim_id = 0; flexe_shim_id < TMM_MAX_FLEXE_SHIM_CNT; flexe_shim_id++)
    {
        for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CLIENT); i++)
        {
            MAC_LOCK;
            sal_memset(&client_link_status, 0, sizeof(ctc_flexe_link_event_t));
            tmp_client_node = NULL;
            tmp_group_node = NULL;
            _sys_tmm_flexe_client_lookup_by_xc_chid(lchip, flexe_shim_id, i, &tmp_client_node);
            if(!tmp_client_node)
            {
                MAC_UNLOCK;
                continue;
            }
            _sys_tmm_flexe_group_lookup(lchip, tmp_client_node->group_id, &tmp_group_node);
            if (!tmp_group_node)
            {
                MAC_UNLOCK;
                continue;
            }
            if ((SYS_FLEXE_GROUP_TX_IDLE != tmp_group_node->tx.crac_state) || (SYS_FLEXE_GROUP_RX_IDLE != tmp_group_node->rx.crac_state))
            {
                MAC_UNLOCK;
                continue;
            } 
            _sys_tmm_flexe_alarm_client_mismatch(lchip, tmp_client_node, &event_action);
            if(SYS_FLEXE_EVENT_NONE == event_action)
            {
                MAC_UNLOCK;
                continue;
            }
            client_link_status.client_id = tmp_client_node->client_id;
            if (SYS_FLEXE_EVENT_SET == event_action)
            {
                client_link_status.link_status = 2;
            }
            else
            {
                client_link_status.link_status = 3;
            }
            MAC_UNLOCK;
            /* cb */
            CTC_ERROR_RETURN(sys_usw_interrupt_get_event_cb(lchip, CTC_EVENT_FLEXE_LINK, &cb));
            if (cb)
            {
                cb(gchip_id, &client_link_status);
            }
        }
    }

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_monitor_cr_timer(uint8 lchip)
{
    uint8 inst_id          = 0;
    uint8 inst_bmp         = 0;
    uint8 per_shim_inst_id = 0;
    uint8 flexe_shim_id    = 0;
    uint8 is_recv_ca       = 0;
    uint8 is_timeout       = TRUE;
    uint32 clk_cnt         = 0;
    uint32 group_id        = 0;

    for (inst_id = 0; inst_id < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT) * TMM_MAX_FLEXE_SHIM_CNT; inst_id ++)
    {
        flexe_shim_id = inst_id / MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT);
        per_shim_inst_id = inst_id % MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT);

        if (0 == p_usw_flexe_master[lchip]->cr_timer[flexe_shim_id][per_shim_inst_id].clk_cnt)
        {
            continue;
        }

        clk_cnt = (-- p_usw_flexe_master[lchip]->cr_timer[flexe_shim_id][per_shim_inst_id].clk_cnt);
        group_id = p_usw_flexe_master[lchip]->cr_timer[flexe_shim_id][per_shim_inst_id].group_id;
        inst_bmp = p_usw_flexe_master[lchip]->cr_timer[flexe_shim_id][per_shim_inst_id].inst_bmp;

        if (0 == clk_cnt)
        {
            (void)_sys_tmm_flexe_get_is_recv_ca_and_cr_timeout(lchip, flexe_shim_id, per_shim_inst_id, &is_recv_ca, NULL);
            FLEXE_DUMP("\n    [CR_TIMER]%s @ %d, group %d clock count reduce to zero\n", __FUNCTION__, __LINE__, group_id);
            FLEXE_DUMP("            %-16s : %u [%s]\n", "is_recv_ca", is_recv_ca, (is_recv_ca ? "YES" : "NO"));
            FLEXE_DUMP("            %-16s : %s\n", "TimeOut",(is_recv_ca ? "NO" : "YES"));

            if (FALSE == is_recv_ca)
            {
                (void)_sys_tmm_flexe_set_is_recv_ca_and_cr_timeout(lchip, flexe_shim_id, inst_bmp, NULL, &is_timeout);

                /* cr timeout alarm */
                _sys_tmm_flexe_alarm_cr_timeout(lchip, group_id, TRUE);

                /* rollback send cr  */
                _sys_tmm_flexe_rollback_send_cr(lchip, group_id);
            }
        }
    }

    return CTC_E_NONE;
}


#define ____FLEXE_ISR____

int32
sys_tmm_flexe_intr_dispatch(uint8 lchip, uint32 flexe_shim_id, void* p_data, void* p_data_mask)
{
    uint8   idx;
    uint8   inst_id = 0;
    uint32* p_bmp = (uint32*)p_data;  //word 0~4  5 in total
    uint32* p_bmp_mask = (uint32*)p_data_mask;  //word 0~4  5 in total
    sys_flexe_group_t *tmp_group_node = NULL;

    if((0 == p_bmp[0]) && (0 == p_bmp[1]) && (0 == p_bmp[2]) && (0 == p_bmp[3]) && (0 == p_bmp[4]))
    {
        FLEXE_DBG_PRINTF("\n   No CR/CA fall/rise occur!\n\n");
        return CTC_E_NONE;
    }

    for(idx = 0; idx < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT)*2; idx++)
    {
        if(SYS_SET_BIT_CHECK(p_bmp[g_cr_intr_list[idx][SYS_FLEXE_INTR_BMP_IDX]], g_cr_intr_list[idx][SYS_FLEXE_INTR_MASK])
            && !SYS_SET_BIT_CHECK(p_bmp_mask[g_cr_intr_list[idx][SYS_FLEXE_INTR_BMP_IDX]], g_cr_intr_list[idx][SYS_FLEXE_INTR_MASK]))
        {
            inst_id = g_cr_intr_list[idx][SYS_FLEXE_INTR_INST];
            tmp_group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, flexe_shim_id, inst_id);
            SYS_CONDITION_CONTINUE(!tmp_group_node);

            //CTC_ERROR_RETURN(_sys_tmm_flexe_rx_cr_isr(lchip, tmp_group_node, inst_id));
        }

        if(SYS_SET_BIT_CHECK(p_bmp[g_ca_intr_list[idx][SYS_FLEXE_INTR_BMP_IDX]], g_ca_intr_list[idx][SYS_FLEXE_INTR_MASK])
            && !SYS_SET_BIT_CHECK(p_bmp_mask[g_ca_intr_list[idx][SYS_FLEXE_INTR_BMP_IDX]], g_ca_intr_list[idx][SYS_FLEXE_INTR_MASK]))
        {
            inst_id = g_ca_intr_list[idx][SYS_FLEXE_INTR_INST];
            tmp_group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, flexe_shim_id, inst_id);
            SYS_CONDITION_CONTINUE(!tmp_group_node);

            //CTC_ERROR_RETURN(_sys_tmm_flexe_rx_ca_isr(lchip, tmp_group_node, inst_id));
        }

        if(SYS_SET_BIT_CHECK(p_bmp[g_ohlock_intr_list[idx][SYS_FLEXE_INTR_BMP_IDX]], g_ohlock_intr_list[idx][SYS_FLEXE_INTR_MASK])
            && !SYS_SET_BIT_CHECK(p_bmp_mask[g_ohlock_intr_list[idx][SYS_FLEXE_INTR_BMP_IDX]], g_ohlock_intr_list[idx][SYS_FLEXE_INTR_MASK]))
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_alarm_ohlock_ohmflock_isr(lchip, flexe_shim_id, g_ohlock_intr_list[idx][SYS_FLEXE_INTR_INST], 
                g_ohlock_intr_list[idx][SYS_FLEXE_INTR_VALUE], CTC_FLEXE_EVENT_LOF));
        }

        if(SYS_SET_BIT_CHECK(p_bmp[g_ohmflock_intr_list[idx][SYS_FLEXE_INTR_BMP_IDX]], g_ohmflock_intr_list[idx][SYS_FLEXE_INTR_MASK])
            && !SYS_SET_BIT_CHECK(p_bmp_mask[g_ohmflock_intr_list[idx][SYS_FLEXE_INTR_BMP_IDX]], g_ohmflock_intr_list[idx][SYS_FLEXE_INTR_MASK]))
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_alarm_ohlock_ohmflock_isr(lchip, flexe_shim_id, g_ohmflock_intr_list[idx][SYS_FLEXE_INTR_INST], 
                g_ohmflock_intr_list[idx][SYS_FLEXE_INTR_VALUE], CTC_FLEXE_EVENT_LOMF));
        }
            
        if(SYS_SET_BIT_CHECK(p_bmp[g_rpf_intr_list[idx][SYS_FLEXE_INTR_BMP_IDX]], g_rpf_intr_list[idx][SYS_FLEXE_INTR_MASK]))
        {
            CTC_ERROR_RETURN(_sys_tmm_flexe_alarm_rpf_isr(lchip, flexe_shim_id, g_rpf_intr_list[idx][SYS_FLEXE_INTR_INST], 
                g_rpf_intr_list[idx][SYS_FLEXE_INTR_VALUE]));
        }            
    }

    return CTC_E_NONE;
}

void
_sys_tmm_flexe_func_isr(uint8 lchip, uint8 flexe_shim_id)
{
    uint32 index  = 0;
    uint32 tbl_id = 0;
    uint32 cmd    = 0;
    uint32 i      = 0;
    FlexeMgrInterruptFunc_m  flexemgr_intr;

    uint32 bmp[5] = {0};
    uint32 bmp_mask[5] = {0};
    uint32 addr_flexe_intr[2][5] = 
    {
        {0x61050080, 0x61050084, 0x61050088, 0x6105008c, 0x61050090},
        {0x69050080, 0x69050084, 0x69050088, 0x6905008c, 0x69050090},
    };

    uint32 addr_flexe_intr_mask[2][5] = 
    {
        {0x610500c0, 0x610500c4, 0x610500c8, 0x610500cc, 0x610500d0},
        {0x690500c0, 0x690500c4, 0x690500c8, 0x690500cc, 0x690500d0},
    };

    /*************** TxClientSchEnB start! ****************/
    /* #1, calc index */
    index = DRV_INS(flexe_shim_id, 0);

    /* #2, read HW table */
    tbl_id = FlexeMgrInterruptFunc_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &flexemgr_intr);

    for(i = 0; i < 5; i++)
    {
        (void)(drv_usw_chip_read(lchip, addr_flexe_intr[flexe_shim_id][i], &(bmp[i])));
        (void)(drv_usw_chip_read(lchip, addr_flexe_intr_mask[flexe_shim_id][i], &(bmp_mask[i])));
    }
    (void)(sys_tmm_flexe_intr_dispatch(lchip, flexe_shim_id, (void*)bmp, (void*)bmp_mask));
}

/*
  Flexe event isr cb function
*/
int32
sys_tmm_flexe_event_isr(uint8 lchip, uint32 intr, void* p_data)
{
    uint8 flexe_shim_id = 0;
    uint8 inst_id       = 0;
    uint8 c_intr        = 0;
    sys_intr_flexe_status_t flexe_status;
    sys_flexe_group_t *group_node = NULL;

    /* decode flexe intr to identify real event to process */
    if ((SYS_INTR_FUNC_FLEX_DP0 == intr) || (SYS_INTR_FUNC_FLEX_DP1 == intr))
    {
        flexe_shim_id = (intr - SYS_INTR_FUNC_FLEX_DP0);
        _sys_tmm_flexe_func_isr(lchip, flexe_shim_id);
    }
    else if (SYS_INTR_CHIP_NORMAL == intr)
    {
        sal_memcpy(&flexe_status, (sys_intr_flexe_status_t*)p_data, sizeof(sys_intr_flexe_status_t));
        if (flexe_status.evt_bmp & (1 << CTC_FLEXE_EVENT_RX_SWITCH_OK))
        {
            flexe_shim_id = flexe_status.dp;
            inst_id       = flexe_status.flexe_ins;
            /* get group_node from asic_inst id */
            group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, flexe_shim_id, inst_id);
            SYS_CONDITION_RETURN(!group_node, CTC_E_NONE);

            c_intr = ((flexe_status.p_status[0] >> 15) & 0x1);
            SYS_CONDITION_RETURN((group_node->rx.active == c_intr), CTC_E_NONE);

            //_sys_tmm_flexe_rx_c_isr(lchip, group_node, inst_id);
        }
    }

    return CTC_E_NONE;
}

int32 sys_tmm_flexe_update_misc(uint8 lchip)
{
    sys_flexe_client_t* p_client = NULL;
    ctc_slistnode_t* node = NULL;
    uint32 speed_val = 0;

    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
    {
        p_client = _ctc_container_of(node, sys_flexe_client_t, head);
        SYS_CONDITION_CONTINUE(SYS_FLEXE_UNUSED_FLAG_U32 == p_client->group_id);
        _sys_tmm_flexe_get_client_speed_val(lchip, p_client, SYS_FLEXE_DIR_TX, SYS_FLEXE_ACTIVE_FLAG, &speed_val);
        SYS_CONDITION_CONTINUE((SYS_FLEXE_UNUSED_FLAG_U32 == speed_val) || !speed_val);
        SYS_CB(SYS_CB_SCOAM_SET_CLIENT_SPEED, lchip, speed_val, p_client->client_id);
    }

    return CTC_E_NONE;
}

#define ____FLEXE_DEBUG____

int32
sys_tmm_flexe_debug_show_status(uint8 lchip)
{
    uint8 i                 = 0;
    uint8 flag_group        = 0;
    uint8 flag_client       = 0;
    uint8 flexe_shim_id     = 0;
    uint8 mii_link          = 0;
    uint8 pcs_link          = 0;
    uint8 ohlock            = 0;
    uint8 ohmflock          = 0;
    uint8 rpf               = 0;
    uint8 padlock           = 0;
    uint32 rx_table         = 0;
    uint32 tx_table         = 0;
    uint32 tmp_nettx        = 0;
    uint32 tx_speed         = 0;
    uint32 rx_speed         = 0;
    uint32 max_speed        = 0;
    uint32 inst_group_id[TMM_MAX_FLEXE_SHIM_CNT][SYS_FLEXE_MAX_INST_CNT];
    int32 ret               = 0;
    sys_flexe_group_t* group_node = NULL;
    sys_flexe_client_t* client_node = NULL;
    sys_datapath_lport_attr_t* port_attr = NULL;
    ctc_slistnode_t* node = NULL;

    sal_memset(inst_group_id, SYS_FLEXE_UNUSED_FLAG_U32, sizeof(inst_group_id));
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "----------------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "FlexE group list:\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-----------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    %-6s%-10s%-10s%-10s%-10s\n", "ID", "rx_sw", "rx_hw", "tx_sw", "tx_hw");
    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->group_list, node)
    {
        group_node = _ctc_container_of(node, sys_flexe_group_t, head);
        SYS_CONDITION_CONTINUE(!group_node);
        SYS_CONDITION_CONTINUE(SYS_FLEXE_UNSUPP == flexe_shim_id);
        SYS_CONDITION_CONTINUE(!group_node->inst_cnt);
        flexe_shim_id = group_node->flexe_shim_id;
        flag_group = 1;

        for(i = 0; i < group_node->inst_cnt; i++)
        {
            inst_group_id[flexe_shim_id][group_node->inst_list[i]] = group_node->group_id;
        }
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    %-6u", group_node->group_id);
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10s", (SYS_FLEXE_ACTIVE_B == group_node->rx.active) ? "B" : "A");
        ret = _sys_tmm_flexe_get_group_manual_table(lchip, group_node, SYS_FLEXE_DIR_RX, &rx_table);
        if (0 != ret) 
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10s", "ERROR");
        }
        else
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10s", (SYS_FLEXE_ACTIVE_B == rx_table) ? "B" : "A");
        }
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10s", (SYS_FLEXE_ACTIVE_B == group_node->tx.active) ? "B" : "A");
        ret = _sys_tmm_flexe_get_group_manual_table(lchip, group_node, SYS_FLEXE_DIR_TX, &tx_table);
        if (0 != ret) 
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10s\n", "ERROR");
        }
        else
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10s\n", (SYS_FLEXE_ACTIVE_B == tx_table) ? "B" : "A");
        }
    }
    if (0 == flag_group)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  No group created\n");
    }

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-----------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "FlexE client list:\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-----------------------------------------------------------------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    %-6s%-10s%-14s%-6s%-6s%-6s%-6s%-12s%-10s%-10s%-8s%-10s%-10s\n", \
        "ID", "Group_ID", "Client_number", "Gport", "Chan", "Mac", "TXQM", "Port_Speed", "Tx_Speed", "Rx_Speed", "Credit", "Mismatch", "Mac_link");
    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->client_list, node)
    {
        client_node = _ctc_container_of(node, sys_flexe_client_t, head);
        if (client_node)
        {
            flag_client = 1;

            if (SYS_FLEXE_UNUSED_FLAG_U32 == client_node->client_id)
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    %-6s", "NA");
            }
            else
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    %-6u", client_node->client_id);
            }
            if (SYS_FLEXE_UNUSED_FLAG_U32 == client_node->group_id)
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10s", "NA");
            }
            else
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10u", client_node->group_id);
            }
            if (0 == client_node->client_number)
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-14s", "NA");
            }
            else
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-14u", client_node->client_number);
            }
            if (SYS_FLEXE_UNUSED_FLAG_U32 == client_node->gport)
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-6s", "NA");
            }
            else
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-6u", client_node->gport);
            }
            if (SYS_FLEXE_UNUSED_FLAG_U8 == client_node->chan_id)
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-6s", "NA");
            }
            else
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-6u", client_node->chan_id);
            }
            if (SYS_FLEXE_UNUSED_FLAG_U16 == client_node->mac_id)
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-6s%-6s", "NA", "NA");
            }
            else
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-6u%-6u", client_node->mac_id, client_node->mac_id/40);
            }

            if (SYS_FLEXE_UNUSED_FLAG_U32 != client_node->gport)
            {
                port_attr = sys_usw_datapath_get_port_capability(lchip, CTC_MAP_GPORT_TO_LPORT(client_node->gport));
                if (!port_attr)
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-12s", "NA");
                }
                else
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-12u", port_attr->speed_value);
                }
            }
            else
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-12s", "NA");
            }
            _sys_tmm_flexe_get_client_speed_val(lchip, client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_ACTIVE_FLAG, &tx_speed);
            _sys_tmm_flexe_get_client_speed_val(lchip, client_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_ACTIVE_FLAG, &rx_speed);
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10u", tx_speed);
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10u", rx_speed);
            max_speed = (tx_speed > rx_speed) ? tx_speed : rx_speed;
            tmp_nettx = _sys_tmm_nettx_speed_to_credit(max_speed);
            if (SYS_FLEXE_UNUSED_FLAG_U16 == client_node->mac_id)
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-8s", "NA");
            }
            else
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-8u", tmp_nettx);
            }
            if (CTC_IS_BIT_SET(client_node->event_bmp, SYS_FLEXE_EVENT_CLIENT_MISMATCH))
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10s", "trigger");
            }
            else
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10s", "clear");
            }
            _sys_tmm_flexe_get_client_mii_link_status(lchip, client_node, &mii_link);
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10u\n", mii_link);
        }
    }
    if (0 == flag_client)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  No client added\n");
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-----------------------------------------------------------------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "FlexE instance list:\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-----------------------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  FlexE shim 0:\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-----------------------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    %-11s%-15s%-10s%-10s%-10s%-10s%-10s\n", "Instance", "Group ID", "Pcs_link", "Ohlock", "Ohmflock", "RPF", "Padlock");
    flexe_shim_id = 0;
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        if (SYS_FLEXE_UNUSED_FLAG_U32 == inst_group_id[flexe_shim_id][i])
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    %-11d%-15s\n", i, "Not Used");
        }
        else
        {
            _sys_tmm_flexe_get_inst_pcs_link_status(lchip, flexe_shim_id, i, &pcs_link);
            _sys_tmm_flexe_clear_inst_ohlock(lchip, flexe_shim_id, i);
            _sys_tmm_flexe_get_inst_ohlock(lchip, flexe_shim_id, i, &ohlock);
            _sys_tmm_flexe_get_inst_ohmflock(lchip, flexe_shim_id, i, &ohmflock);
            _sys_tmm_flexe_get_inst_rpf(lchip, flexe_shim_id, i, &rpf);
            _sys_tmm_flexe_get_inst_padlock(lchip, flexe_shim_id, i, &padlock);
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    %-11d%-15d%-10d%-10d%-10d%-10d%-10d\n", i, inst_group_id[flexe_shim_id][i], pcs_link, ohlock, ohmflock, rpf, padlock);
        }
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-----------------------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  FlexE shim 1:\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-----------------------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    %-11s%-15s%-10s%-10s%-10s%-10s%-10s\n", "Instance", "Group ID", "Pcs_link", "Ohlock", "Ohmflock", "RPF", "Padlock");
    flexe_shim_id = 1;
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        if (SYS_FLEXE_UNUSED_FLAG_U32 == inst_group_id[flexe_shim_id][i])
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    %-11d%-15s\n", i, "Not Used");
        }
        else
        {
            _sys_tmm_flexe_get_inst_pcs_link_status(lchip, flexe_shim_id, i, &pcs_link);
            _sys_tmm_flexe_clear_inst_ohlock(lchip, flexe_shim_id, i);
            _sys_tmm_flexe_get_inst_ohlock(lchip, flexe_shim_id, i, &ohlock);
            _sys_tmm_flexe_get_inst_ohmflock(lchip, flexe_shim_id, i, &ohmflock);
            _sys_tmm_flexe_get_inst_rpf(lchip, flexe_shim_id, i, &rpf);
            _sys_tmm_flexe_get_inst_padlock(lchip, flexe_shim_id, i, &padlock);
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    %-11d%-15d%-10d%-10d%-10d%-10d%-10d\n", i, inst_group_id[flexe_shim_id][i], pcs_link, ohlock, ohmflock, rpf, padlock);
        }
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "------------------------------------------------------------------------------\n");

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_debug_show_group(uint8 lchip, uint32 group_id)
{
    uint8 i = 0, j = 0;
    uint8 logical_serdes_id = 0;
    uint8 physical_serdes_id = 0;
    uint8 phy_lane_num = 0;
    int32 ret = 0;
    uint32 rx_table = 0;
    uint32 tx_table = 0;
    uint32 client_cal[SYS_FLEXE_MAX_INST_CNT][10] = {{0}};    
    sys_flexe_group_t* group_node = NULL;

    _sys_tmm_flexe_group_lookup(lchip, group_id, &group_node);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] group ID %d not exist!\n", group_id);
        ret = CTC_E_NOT_EXIST;
        return ret;
    }

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "----------------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "FlexE group ID \t%u(0x%x) : \n", group_id, group_id);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " flexe_shim_id: ");
    if (SYS_FLEXE_UNSUPP == group_node->flexe_shim_id)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "Not Set\n");
    }
    else
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%d\n", group_node->flexe_shim_id);
    }

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " group number : ");
    if (0 == group_node->group_number)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "Not Set\n");
    }
    else
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%u(0x%x)\n", group_node->group_number, group_node->group_number);
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " switch_mode  : %d\n", group_node->switch_mode);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " rx_cfg_mode  : %d\n", group_node->rx_cfg_mode);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " inst_cnt     : %d\n", group_node->inst_cnt);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " phy_cnt      : %d\n", group_node->phy_cnt);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " event_bmp    : %d\n", group_node->event_bmp);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " cr_timer     : %d\n", group_node->cr_timer);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " phy_type     : ");
    if (0 == group_node->phy_cnt)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-");
    }
    else
    {
        switch (group_node->phy_list[0].pcs_mode)
        {
        case CTC_CHIP_SERDES_LG_MODE:
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "50G-R2");
            break;
        case CTC_CHIP_SERDES_LG_R1_MODE:
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "50G-R1");
            break;
        case CTC_CHIP_SERDES_CG_R2_MODE:
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "100G-R2");
            break;
        case CTC_CHIP_SERDES_CCG_R4_MODE:
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "200G-R4");
            break;
        case CTC_CHIP_SERDES_CDG_R8_MODE:
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "400G-R8");
            break;
        case CTC_CHIP_SERDES_CG_MODE:
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "100G-R4");
            break;
        default:
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "UNSUPP");
            break;
        } 
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " fec_type     : ");
    if (0 == group_node->phy_cnt)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-");
    }
    else
    {
        switch (group_node->phy_list[0].fec_type)
        {
        case CTC_PORT_FEC_TYPE_RS:
        case CTC_PORT_FEC_TYPE_RS528:
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "Rs528");
            break;
        case CTC_PORT_FEC_TYPE_RS544:
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "Rs544");
            break;
        case CTC_PORT_FEC_TYPE_RS272:
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "Rs272");
            break;
        case CTC_PORT_FEC_TYPE_NONE:
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "NONE");
            break;
        default:
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "UNSUPP");
            break;
        }  
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-----------TX------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " sw active    : %s\n", (SYS_FLEXE_ACTIVE_B == group_node->tx.active) ? "B" : "A");
    if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A))
    {
        ret = _sys_tmm_flexe_get_group_manual_table(lchip, group_node, SYS_FLEXE_DIR_TX, &tx_table);
        if (0 != ret) 
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " hw active    : %s\n", "ERROR");
        }
        else
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " hw active    : %s\n", (SYS_FLEXE_ACTIVE_B == tx_table) ? "B" : "A");
        }
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " CRCAC State  : ");
    switch (group_node->tx.crac_state)
    {
    case SYS_FLEXE_GROUP_TX_CR_SENT:
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "CR SENT");
        break;
    case SYS_FLEXE_GROUP_TX_CA_RCV:
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "CA RCV");
        break;
    case SYS_FLEXE_GROUP_TX_C_SENT:
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "C SENT");
        break;
    case SYS_FLEXE_GROUP_TX_IDLE:
    default:
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "IDLE");
        break;
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-----------RX------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " sw active    : %s\n", (SYS_FLEXE_ACTIVE_B == group_node->rx.active) ? "B" : "A");
    if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A))
    {
        ret = _sys_tmm_flexe_get_group_manual_table(lchip, group_node, SYS_FLEXE_DIR_RX, &rx_table);
        if (0 != ret) 
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " hw active    : %s\n", "ERROR");
        }
        else
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " hw active    : %s\n", (SYS_FLEXE_ACTIVE_B == rx_table) ? "B" : "A");
        }
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " CRCAC State  : ");
    switch (group_node->rx.crac_state)
    {
    case SYS_FLEXE_GROUP_RX_CR_RCV:
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "CR RCV");
        break;
    case SYS_FLEXE_GROUP_RX_CA_SENT:
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "CA SENT");
        break;
    case SYS_FLEXE_GROUP_RX_C_RCV:
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "C RCV");
        break;
    case SYS_FLEXE_GROUP_RX_IDLE:
    default:
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "IDLE");
        break;
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------\n");

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " group phy list: \n");
    if (0 == group_node->phy_cnt)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "---------------------------------------------------\n");
        return CTC_E_NONE;
    }
    _sys_tmm_flexe_get_phy_lane_num(lchip, group_node->phy_list[0].logical_serdes_base, &phy_lane_num);
    for (i = 0; i < group_node->phy_cnt; i++)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "----------------------------------------\n");
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\tphy_index          : %d\n", i);

        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\tlogical_serdes_id  : ");
        for (j = 0; j < phy_lane_num; j++)
        {
            logical_serdes_id = group_node->phy_list[i].logical_serdes_base + j;
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%d ", logical_serdes_id);
        }
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");

        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\tphysical_serdes_id : ");
        for (j = 0; j < phy_lane_num; j++)
        {
            logical_serdes_id = group_node->phy_list[i].logical_serdes_base + j;
            _sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, logical_serdes_id, &physical_serdes_id);
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%d ", physical_serdes_id);
        }
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");

        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\tinst_base          : ");
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%d\n", group_node->phy_list[i].inst_base);

        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\tphy_number         : ");
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%d\n", group_node->phy_list[i].phy_number);
    }

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "----------------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " TX slot client_number:\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-----------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " CFG:\n");
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_asic_slot(lchip, group_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_CFG_FLAG, client_cal));
    for (i = 0; i < 8; i++)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " inst_%d   ", i);
        for (j = 0; j < 10; j++)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-4d, ", client_cal[i][j]);
        }
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " A:\n");
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_asic_slot(lchip, group_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_ACTIVE_A, client_cal));
    for (i = 0; i < 8; i++)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " inst_%d   ", i);
        for (j = 0; j < 10; j++)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-4d, ", client_cal[i][j]);
        }
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " B:\n");
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_asic_slot(lchip, group_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_ACTIVE_B, client_cal));
    for (i = 0; i < 8; i++)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " inst_%d   ", i);
        for (j = 0; j < 10; j++)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-4d, ", client_cal[i][j]);
        }
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "----------------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " RX slot client_number:\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "----------------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " CFG:\n");
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_asic_slot(lchip, group_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_CFG_FLAG, client_cal));
    for (i = 0; i < 8; i++)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " inst_%d   ", i);
        for (j = 0; j < 10; j++)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-4d, ", client_cal[i][j]);
        }
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " A:\n");
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_asic_slot(lchip, group_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_ACTIVE_A, client_cal));
    for (i = 0; i < 8; i++)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " inst_%d   ", i);
        for (j = 0; j < 10; j++)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-4d, ", client_cal[i][j]);
        }
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " B:\n");
    CTC_ERROR_RETURN(_sys_tmm_flexe_get_group_asic_slot(lchip, group_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_ACTIVE_B, client_cal));
    for (i = 0; i < 8; i++)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " inst_%d   ", i);
        for (j = 0; j < 10; j++)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-4d, ", client_cal[i][j]);
        }
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "----------------------------------------------------------------------\n");

    return ret;
}

int32
sys_tmm_flexe_debug_show_client(uint8 lchip, uint32 client_id)
{
    uint8 i                 = 0;
    uint8 j                 = 0;
    uint8 slot              = 0;
    uint32 cfg_speed        = 0;
    uint32 active_speed     = 0;
    uint32 inactive_speed   = 0;
    int32 ret               = 0;

    sys_flexe_client_t* client_node = NULL;
    sys_flexe_group_t* group_node = NULL;
    sys_datapath_lport_attr_t* port_attr = NULL;

    _sys_tmm_flexe_client_lookup(lchip, client_id, &client_node);
    if (!client_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] client ID %d not exist!\n", client_id);
        ret = CTC_E_NOT_EXIST;
        return ret;
    }

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "----------------------------------------------------------------------\n");
    if (SYS_FLEXE_UNUSED_FLAG_U32 == client_node->group_id)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  group_id: \t%s\n", "Unknown");
    }
    else
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  group_id: \t%u\n", client_node->group_id);
    }
    if (0 == client_node->client_number)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  client_num: \t%s\n", "Not Set");
    }
    else
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  client_num: \t%u(0x%x)\n", client_node->client_number, client_node->client_number);
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "------------------------------\n");

    if (SYS_FLEXE_UNUSED_FLAG_U8 == client_node->chan_id)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  chan: \t%s\n", "Unknown");
    }
    else
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  chan: \t%u\n", client_node->chan_id);
    }

    if (SYS_FLEXE_UNUSED_FLAG_U16 == client_node->mac_id)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  mac_id: \t%s\n", "Unknown");
    }
    else
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  mac_id: \t%u\n", client_node->mac_id);
    }

    if (SYS_FLEXE_UNSUPP == client_node->flexe_shim_id)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  DP id: \t%s\n", "Unknown");
    }
    else
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  DP id: \t%d\n", client_node->flexe_shim_id);
    }

    if (0 == client_node->shim_chid)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  shim_chid: \t%s\n", "Unknown");
    }
    else
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  shim_chid: \t%d\n", client_node->shim_chid);
    }

    if (SYS_FLEXE_UNUSED_FLAG_U8 == client_node->tx_xc_chid)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  tx_xc_chid: \t%s\n", "Unknown");
    }
    else
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  tx_xc_chid: \t%d\n", client_node->tx_xc_chid);
    }
    if (SYS_FLEXE_UNUSED_FLAG_U8 == client_node->rx_xc_chid)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  rx_xc_chid: \t%s\n", "Unknown");
    }
    else
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  rx_xc_chid: \t%d\n", client_node->rx_xc_chid);
    }
    if (SYS_FLEXE_UNUSED_FLAG_U32 == client_node->cross_client_id)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  cross_client: %s\n", "Unknown");
    }
    else
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  cross_client: %d\n", client_node->cross_client_id);
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  flow type: \t%s\n", ((SYS_FLEXE_FLOW_TYPE_B==client_node->flow_type)\
                                                                ?"Flow B":((SYS_FLEXE_FLOW_TYPE_C==client_node->flow_type)\
                                                                ?"Flow C":((SYS_FLEXE_FLOW_TYPE_A==client_node->flow_type)\
                                                                ?"Flow A":"Unknown"))));
    if (SYS_FLEXE_UNUSED_FLAG_U32 == client_node->gport)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  gport: \t%s\n", "Not Set");
    }
    else
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  gport: \t%u\n", client_node->gport);
        port_attr = sys_usw_datapath_get_port_capability(lchip, CTC_MAP_GPORT_TO_LPORT(client_node->gport));
        if (port_attr && port_attr->client_bind_num == 2)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%20s\n"," client APS Enable: ");
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%20s%4u\n","  working client: ", port_attr->flexe_client);
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%20s%4u\n","  protect client: ", port_attr->flexe_client_aps);
        }
    }

    _sys_tmm_flexe_group_lookup(lchip, client_node->group_id, &group_node);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "----------------------------------------------------------------------\n");
        return CTC_E_NONE;
    }

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "--------------tx--------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  sw active     : %s\n", (SYS_FLEXE_ACTIVE_B == group_node->tx.active) ? "B" : "A");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  op            : %s\n", ((SYS_FLEXE_CLIENT_ADD==client_node->tx.op)\
                                                                ?"add":((SYS_FLEXE_CLIENT_REMOVE==client_node->tx.op)\
                                                                ?"remove":((SYS_FLEXE_CLIENT_RESIZE==client_node->tx.op)\
                                                                ?"resize":"none slot"))));
    _sys_tmm_flexe_get_client_speed_val(lchip, client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_CFG_FLAG,      &cfg_speed);
    _sys_tmm_flexe_get_client_speed_val(lchip, client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_ACTIVE_FLAG,   &active_speed); 
    _sys_tmm_flexe_get_client_speed_val(lchip, client_node, SYS_FLEXE_DIR_TX, SYS_FLEXE_INACTIVE_FLAG, &inactive_speed);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  cfg_speed     : %d\n", cfg_speed);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  active_speed  : %d\n", active_speed);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  inactive_speed: %d\n", inactive_speed);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  cfg_slot      : ");
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            if (client_node->shim_chid == group_node->tx.dir_inst[i].slot_cfg_shim_chid[j])
            {
                slot = group_node->inst_list[i]*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) + j;
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-2d ", slot);
            }
        }
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  active_slot   : ");
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            if (((SYS_FLEXE_ACTIVE_B == group_node->tx.active) && (client_node->shim_chid == group_node->tx.dir_inst[i].switch_shim_chid_b[j])) ||\
                ((SYS_FLEXE_ACTIVE_A == group_node->tx.active) && (client_node->shim_chid == group_node->tx.dir_inst[i].switch_shim_chid_a[j])))
            {
                slot = group_node->inst_list[i]*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) + j;
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-2d ", slot);
            }
        }
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  inactive_slot : ");
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            if (((SYS_FLEXE_ACTIVE_B == group_node->tx.active) && (client_node->shim_chid == group_node->tx.dir_inst[i].switch_shim_chid_a[j])) ||\
                ((SYS_FLEXE_ACTIVE_A == group_node->tx.active) && (client_node->shim_chid == group_node->tx.dir_inst[i].switch_shim_chid_b[j])))
            {
                slot = group_node->inst_list[i]*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) + j;
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-2d ", slot);
            }
        }
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "--------------rx--------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  sw active     : %s\n", (SYS_FLEXE_ACTIVE_B == group_node->rx.active) ? "B" : "A");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  op            : %s\n", ((SYS_FLEXE_CLIENT_ADD==client_node->rx.op)\
                                                                ?"add":((SYS_FLEXE_CLIENT_REMOVE==client_node->rx.op)\
                                                                ?"remove":((SYS_FLEXE_CLIENT_RESIZE==client_node->rx.op)\
                                                                ?"resize":"none slot"))));
    _sys_tmm_flexe_get_client_speed_val(lchip, client_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_CFG_FLAG,      &cfg_speed);
    _sys_tmm_flexe_get_client_speed_val(lchip, client_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_ACTIVE_FLAG,   &active_speed);
    _sys_tmm_flexe_get_client_speed_val(lchip, client_node, SYS_FLEXE_DIR_RX, SYS_FLEXE_INACTIVE_FLAG, &inactive_speed);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  cfg_speed     : %d\n", cfg_speed);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  active_speed  : %d\n", active_speed);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  inactive_speed: %d\n", inactive_speed);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  cfg_slot      : ");
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            if (client_node->shim_chid == group_node->rx.dir_inst[i].slot_cfg_shim_chid[j])
            {
                slot = group_node->inst_list[i]*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) + j;
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-2d ", slot);
            }
        }
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n"); 
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  active_slot   : ");
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            if (((SYS_FLEXE_ACTIVE_B == group_node->rx.active) && (client_node->shim_chid == group_node->rx.dir_inst[i].switch_shim_chid_b[j])) ||\
                ((SYS_FLEXE_ACTIVE_A == group_node->rx.active) && (client_node->shim_chid == group_node->rx.dir_inst[i].switch_shim_chid_a[j])))
            {
                slot = group_node->inst_list[i]*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) + j;
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-2d ", slot);
            }
        }
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  inactive_slot : ");
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); i++)
    {
        for (j = 0; j < MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST); j++)
        {
            if (((SYS_FLEXE_ACTIVE_B == group_node->rx.active) && (client_node->shim_chid == group_node->rx.dir_inst[i].switch_shim_chid_a[j])) ||\
                ((SYS_FLEXE_ACTIVE_A == group_node->rx.active) && (client_node->shim_chid == group_node->rx.dir_inst[i].switch_shim_chid_b[j])))
            {
                slot = group_node->inst_list[i]*MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST) + j;
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-2d ", slot);
            }
        }
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "----------------------------------------------------------------------\n");

    return ret;
}

int32
sys_tmm_flexe_debug_show_inst_status(uint8 lchip, uint8 flexe_shim_id)
{
    uint32 inst_id = 0;
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 step   = 0;
    uint32 factor = 0;
    uint32 val32[16] = {0};

    TxLatchedIntInst0_m  inst_sta_tx;
    RxLatchedIntInst0_m  inst_sta_rx;

    /*************** (I) memset 0 ****************/
    sal_memset(&inst_sta_tx, 0, sizeof(TxLatchedIntInst0_m));
    sal_memset(&inst_sta_rx, 0, sizeof(RxLatchedIntInst0_m));

    SYS_FLEXE_INIT_CHECK();

    if ((0 != flexe_shim_id) && (1 != flexe_shim_id))
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] invalid flexe_shim_id %d!\n", flexe_shim_id);
        return CTC_E_INVALID_PARAM;
    }

    /* TX */
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " -  TxLatchedIntInst[0..7]    \n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-5s%-9s%-11s%-13s%-12s%-13s\n",
                  "Inst", "cBitErr", "calAckErr", "calSwitchEv", "chIdCfgErr", "chanFifoErr");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----------------------------------------------------------------\n");

    for (inst_id = 0; inst_id < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); inst_id++)
    {
        /* #1, calc index */
        index = DRV_INS(flexe_shim_id, 0);

        /* #2, read HW table */
        step = TxLatchedIntInst1_t - TxLatchedIntInst0_t;
        factor = inst_id % 8;
        tbl_id = TxLatchedIntInst0_t + step*factor;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &inst_sta_tx));

        fld_id = TxLatchedIntInst0_cBitErr_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[0], &inst_sta_tx);

        fld_id = TxLatchedIntInst0_calAckErr_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[1], &inst_sta_tx);

        fld_id = TxLatchedIntInst0_calSwitchEv_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[2], &inst_sta_tx);

        fld_id = TxLatchedIntInst0_chIdCfgErr_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[3], &inst_sta_tx);

        fld_id = TxLatchedIntInst0_chanFifoErr_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[4], &inst_sta_tx);

        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-5u%-9u%-11u%-13u%-12u%-13u\n",
              inst_id, val32[0], val32[1], val32[2], val32[3], val32[4]);

        /* #2, clear */
        step = TxGblClrInst1_t - TxGblClrInst0_t;
        factor = inst_id % 8;
        tbl_id =TxGblClrInst0_t + step*factor;
        cmd = DRV_IOW(tbl_id, TxGblClrInst0_intClearSC_f);
        val32[0] = 1;
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &val32[0]));

    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----------------------------------------------------------------\n");

    /* RX */
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " -----------------------------------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " -  RxLatchedIntInst[0..7]  \n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " -----------------------------------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----- f0 : RPF              \n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----- f1 : cBitErr          \n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----- f2 : chIdCfgErr       \n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----- f3 : chanFifoErr      \n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----- f4 : crcErr           \n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----- f5 : deskewOverflow   \n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----- f6 : lossOhLock       \n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----- f7 : lossOhMfLock     \n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----- f8 : calChangeAck     \n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----- f9 : calChangeReq     \n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----- f10: calSwitchEv      \n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----- f11: deskew           \n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----- f12: ohLock           \n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----- f13: ohMfLock         \n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----- f14: ohMfReceived     \n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ----- f15: padLock          \n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " -----------------------------------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-7s%-5s%-5s%-5s%-5s%-5s%-5s%-5s%-5s%-5s%-5s%-5s%-5s%-5s%-5s%-5s%-5s\n",
                  "Inst", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " -----------------------------------------------------------------------------------------\n");

    for (inst_id = 0; inst_id < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT); inst_id++)
    {
        /* #1, calc index */
        index = DRV_INS(flexe_shim_id, 0);

        /* #2, read HW table */
        step = RxLatchedIntInst1_t - RxLatchedIntInst0_t;
        factor = inst_id % 8;
        tbl_id = RxLatchedIntInst0_t + step*factor;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &inst_sta_rx));

        fld_id = RxLatchedIntInst0_RPF_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[0], &inst_sta_rx);

        fld_id = RxLatchedIntInst0_cBitErr_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[1], &inst_sta_rx);

        fld_id = RxLatchedIntInst0_chIdCfgErr_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[2], &inst_sta_rx);

        fld_id = RxLatchedIntInst0_chanFifoErr_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[3], &inst_sta_rx);

        fld_id = RxLatchedIntInst0_crcErr_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[4], &inst_sta_rx);

        fld_id = RxLatchedIntInst0_deskewOverflow_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[5], &inst_sta_rx);

        fld_id = RxLatchedIntInst0_lossOhLock_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[6], &inst_sta_rx);

        fld_id = RxLatchedIntInst0_lossOhMfLock_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[7], &inst_sta_rx);

        fld_id = RxLatchedIntInst0_calChangeAck_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[8], &inst_sta_rx);

        fld_id = RxLatchedIntInst0_calChangeReq_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[9], &inst_sta_rx);

        fld_id = RxLatchedIntInst0_calSwitchEv_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[10], &inst_sta_rx);

        fld_id = RxLatchedIntInst0_deskew_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[11], &inst_sta_rx);

        fld_id = RxLatchedIntInst0_ohLock_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[12], &inst_sta_rx);

        fld_id = RxLatchedIntInst0_ohMfLock_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[13], &inst_sta_rx);

        fld_id = RxLatchedIntInst0_ohMfReceived_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[14], &inst_sta_rx);

        fld_id = RxLatchedIntInst0_padLock_f;
        DRV_IOR_FIELD(lchip, tbl_id, fld_id, &val32[15], &inst_sta_rx);


        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-7u%-5u%-5u%-5u%-5u%-5u%-5u%-5u%-5u%-5u%-5u%-5u%-5u%-5u%-5u%-5u%-5u\n",
                  inst_id, val32[0], val32[1], val32[2], val32[3], val32[4], val32[5], val32[6], val32[7], 
                  val32[8], val32[9], val32[10], val32[11], val32[12], val32[13], val32[14], val32[15]);

        /* #2, clear */
        step = RxGblClrInst1_t - RxGblClrInst0_t;
        factor = inst_id % 8;
        tbl_id = RxGblClrInst0_t + step*factor;
        cmd = DRV_IOW(tbl_id, RxGblClrInst0_intClearSC_f);
        val32[0] = 1;
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &val32[0]));
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " -----------------------------------------------------------------------------------------\n");

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_debug_show_inst_ohram(uint8 lchip, uint8 flexe_shim_id, uint32 inst_id, uint8 dir)
{
    int32 ret                       = CTC_E_NONE;
    uint32 frame_id                 = 0;
    uint32 slot_num                 = 0;
    uint32 frame_num                = 0;
    uint32  val32                   = 0;
    uint8  speed_mode               = 0;
    sys_flexe_group_t*             group_node = NULL;
    sys_flexe_ohram_info_t*        p_ohram_info = NULL;

    SYS_FLEXE_INIT_CHECK();

    p_ohram_info = (sys_flexe_ohram_info_t*)mem_malloc(MEM_DMPS_MODULE, sizeof(sys_flexe_ohram_info_t));
    if(NULL == p_ohram_info)
    {
        ret = CTC_E_NO_MEMORY;
        goto RELEASE_PTR_RETURN;
    }
    sal_memset(p_ohram_info, 0, sizeof(sys_flexe_ohram_info_t));

    /* get group_node from asic_inst id */
    group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, flexe_shim_id, inst_id);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] Asic inst %d not belong to any group!\n", inst_id);
        ret = CTC_E_BADID;
        goto RELEASE_PTR_RETURN;
    }

    _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);

    /* check whether asic_inst is first in the protocol instance */
    if ((inst_id % 2) && (CTC_PORT_SPEED_50G != speed_mode))
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[FlexE] ASIC inst %d is not first in the user instance!\n", inst_id);
        ret = CTC_E_NONE;
        goto RELEASE_PTR_RETURN;
    }

    CTC_ERROR_GOTO(_sys_tmm_flexe_parse_ohram(lchip, group_node, inst_id, p_ohram_info, dir), ret, RELEASE_PTR_RETURN);

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ------------------------------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-35s : %d\n", "sc", p_ohram_info->sc);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-35s : 0x%x\n", "group number", p_ohram_info->group_num);
    if ((CTC_PORT_SPEED_50G == speed_mode) || (CTC_PORT_SPEED_100G == speed_mode))
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-35s : 0x%x\n", "phy number", p_ohram_info->inst_num);
    }
    else if (CTC_PORT_SPEED_200G == speed_mode)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-35s : 0x%x\n", "phy number", p_ohram_info->inst_num >> 1);
    }
    else if (CTC_PORT_SPEED_400G == speed_mode)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-35s : 0x%x\n", "phy number", p_ohram_info->inst_num >> 2);
    }

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-35s : 0x%x\n", "instance number", p_ohram_info->inst_num);

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-35s : %d\n", "CR", p_ohram_info->cr);
    if (SYS_FLEXE_DIR_RX == dir)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-35s : %d\n", "CA", p_ohram_info->ca);
    }
    else
    {
        _sys_tmm_flexe_get_inst_tx_caval(lchip, flexe_shim_id, inst_id, &val32);
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-35s : %d\n", "CA", val32);
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-35s : %d\n", "C[0]", p_ohram_info->c0);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-35s : %d\n", "C[1]", p_ohram_info->c1);
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-35s : %d\n", "C[2]", p_ohram_info->c2);

    if (CTC_PORT_SPEED_50G != speed_mode)
    {
        frame_num = SYS_FLEXE_OH_FRAME_NUM;
        slot_num = SYS_FLEXE_OH_MAX_SLOT_PER_INST;
    }
    else
    {
        frame_num = SYS_FLEXE_OH_FRAME_NUM_50G;
        slot_num = MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST);
    }

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "+-------------+---------------+--------------------------+--------------------------+\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-14s%-16s%-27s%-27s \n", "OH frame id", "FlexE Map(hex)", "Client Carried Calendar A", "Client Carried Calendar B");
    for (frame_id = 0; frame_id < frame_num; frame_id++)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " ");
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-14d", frame_id);
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-16x", p_ohram_info->flexe_map[frame_id]);
        if (frame_id < slot_num && inst_id < MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT))
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-27d", p_ohram_info->inst_client_map[inst_id][frame_id]);
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-27d", p_ohram_info->inst_client_map_b[inst_id][frame_id]);
        }
        else
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-27s", " ");
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-27s", " ");
        }
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "+-------------+---------------+--------------------------+--------------------------+\n");

RELEASE_PTR_RETURN:
    if (p_ohram_info) mem_free(p_ohram_info);
    return ret;
}

int32
sys_tmm_flexe_debug_show_alarm(uint8 lchip)
{
    uint8 i                     = 0;
    uint8 inst_offset           = 0;
    uint8 flag_group            = 0;
    uint8 flag_phy              = 0;
    uint8 flag_inst             = 0;
    uint8 user_inst_cnt         = 0;
    uint8 flexe_shim_id         = 0;
    uint8 physical_serdes_id    = 0;
    uint8 speed_mode            = 0;
    sys_flexe_group_t* group_node = NULL;
    sys_flexe_phy_t* phy_node = NULL;
    ctc_slistnode_t* node = NULL;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "----------------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "FlexE alarm by group:\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "---------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    %-12s%-18s%-17s\n", "Group_ID", "DESKEW_OVER(0xb)", "CR_TIMEOUT(0xc)");
    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->group_list, node)
    {
        group_node = _ctc_container_of(node, sys_flexe_group_t, head);
        if (group_node)
        {
            flag_group = 1;
            flexe_shim_id = group_node->flexe_shim_id;
            if (SYS_FLEXE_UNSUPP == flexe_shim_id)
            {
                continue;
            }
            if (0 == group_node->phy_cnt)
            {
                continue;
            }            
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    %-12u", group_node->group_id);
            if (CTC_IS_BIT_SET(group_node->event_bmp, CTC_FLEXE_EVENT_GROUP_DESKEW_OVER))
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-18s", "trigger");
            }
            else
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-18s", "clear");
            }
            if (CTC_IS_BIT_SET(group_node->event_bmp, CTC_FLEXE_EVENT_GROUP_CR_TIMEOUT))
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-17s\n", "trigger");
            }
            else
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-17s\n", "clear");
            }
        }
    }
    if (0 == flag_group)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  No group created!\n");
    }

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "---------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "FlexE alarm by phy:\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    %-12s%-12s%-12s%-12s%-12s\n", "Serdes_ID", "RPF(0x6)", "LOF(0x7)", "LOMF(0x8)", "LPF(0xd)");
    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->group_list, node)
    {
        group_node = _ctc_container_of(node, sys_flexe_group_t, head);
        if (!group_node)
        {
            continue;
        }
        for (i = 0; i < group_node->phy_cnt; i++)
        {
            phy_node = &group_node->phy_list[i];
            flag_phy = 1;
            _sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, phy_node->logical_serdes_base, &physical_serdes_id);
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    %-12u", physical_serdes_id);
            if (CTC_IS_BIT_SET(phy_node->event_bmp, CTC_FLEXE_EVENT_RPF))
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-12s", "trigger");
            }
            else
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-12s", "clear");
            }
            if (CTC_IS_BIT_SET(phy_node->event_bmp, CTC_FLEXE_EVENT_LOF))
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-12s", "trigger");
            }
            else
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-12s", "clear");
            }
            if (CTC_IS_BIT_SET(phy_node->event_bmp, CTC_FLEXE_EVENT_LOMF))
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-12s", "trigger");
            }
            else
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-12s", "clear");
            }
            if (CTC_IS_BIT_SET(phy_node->event_bmp, CTC_FLEXE_EVENT_LPF))
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-12s\n", "trigger");
            }
            else
            {
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-12s\n", "clear");
            }
        }
    }
    if (0 == flag_phy)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  No phy binded!\n");
    }

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "FlexE alarm by instance:\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "--------------------------------------------------------------------------------------------------------------------\n");
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    %-12s%-18s%-19s%-19s%-16s%-15s%-15s\n", "Serdes_ID", "Instance_offset",\
        "GRP_NUM_MIS(0x0)", "INST_NUM_MIS(0x1)", "MAP_MIS(0x2)", "CAL_MIS(0x3)", "CRC_ERR(0x9)");
    CTC_SLIST_LOOP(p_usw_flexe_master[lchip]->group_list, node)
    {
        group_node = _ctc_container_of(node, sys_flexe_group_t, head);
        if (!group_node)
        {
            continue;
        }
        _sys_tmm_flexe_get_group_phy_speed(lchip, group_node, &speed_mode);
        switch (speed_mode)
        {
            case CTC_PORT_SPEED_50G:
            case CTC_PORT_SPEED_100G:
                user_inst_cnt = 1;
                break;
            case CTC_PORT_SPEED_200G:
                user_inst_cnt = 2;
                break;
            case CTC_PORT_SPEED_400G:
                user_inst_cnt = 4;
                break;
            default:
                break;
        }
        if (!user_inst_cnt)
        {
            continue;
        }
        flag_inst = 1;
        for (i = 0; i < group_node->phy_cnt; i++)
        {
            phy_node = &group_node->phy_list[i];

            for (inst_offset = 0; inst_offset < user_inst_cnt; inst_offset++)
            {
                _sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, phy_node->logical_serdes_base, &physical_serdes_id);
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    %-12u", physical_serdes_id);
                SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-18u", inst_offset);
                if (CTC_IS_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_GRP_NUM_MISMATCH))
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-19s", "trigger");
                }
                else
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-19s", "clear");
                }
                if (CTC_IS_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_INST_NUM_MISMATCH))
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-19s", "trigger");
                }
                else
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-19s", "clear");
                }
                if (CTC_IS_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_MAP_MISMATCH))
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-16s", "trigger");
                }
                else
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-16s", "clear");
                }
                if (CTC_IS_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_CAL_MISMATCH))
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-15s", "trigger");
                }
                else
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-15s", "clear");
                }
                if (CTC_IS_BIT_SET(phy_node->remote_state[inst_offset].event_bmp, CTC_FLEXE_EVENT_CRC_ERR))
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-15s\n", "trigger");
                }
                else
                {
                    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-15s\n", "clear");
                }
            }
        }
    }
    if (0 == flag_inst)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "  No instance used!\n");
    }

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "--------------------------------------------------------------------------------------------------------------------\n");

    return CTC_E_NONE;
}

int32
sys_tmm_flexe_debug_show_ins_sch(uint8 lchip, uint8 flexe_shim_id, uint8 inst_id, uint8 dir)
{
    uint8 i = 0;
    int8 si = 0;
    uint8 group_inst_offset = 0;
    sys_flexe_group_t* group_node = NULL;
    sys_flexe_group_dir_t *p_group_dir = NULL;

    if(inst_id >= MCHIP_CAP(SYS_CAP_FLEXE_MAX_INST_CNT))
    {
        return CTC_E_INVALID_PARAM;
    }

    group_node = _sys_tmm_flexe_group_lookup_by_inst(lchip, flexe_shim_id, inst_id);
    if (!group_node)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [FlexE] DP %d inst %d not belong to any group!\n", flexe_shim_id, inst_id);
        return CTC_E_INVALID_PARAM;
    }
    _sys_tmm_flexe_get_group_inst_offset_by_asic_inst(lchip, group_node, inst_id, &group_inst_offset);

    p_group_dir = (SYS_FLEXE_DIR_TX == dir) ? &group_node->tx : &group_node->rx;

    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "--------------------- Instance %d Schedule %s Config  ----------------------\n", inst_id, (SYS_FLEXE_DIR_TX == dir)?"TX":"RX");
    for (i = 0; i < MCHIP_CAP(SYS_CAP_FLEXE_MAX_CYCLE); i++)
    {
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "inst CYCLE %2d mask (shim_chid %2d):   ", i, p_group_dir->ic[group_inst_offset][i].shim_chid);
        for (si = MCHIP_CAP(SYS_CAP_FLEXE_MAX_SLOT_PER_INST)-1; si >= 0; si--)
        {
            SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%d,  ", (p_group_dir->ic[group_inst_offset][i].ic_subcalmask >> si) & 0x1);
        }
        SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    }
    SYS_FLEXE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "----------------------------------------------------------------------------\n");

    return CTC_E_NONE;
}


#define ____FLEXE_INIT____
/**
 @brief initialize the flexe module
*/
int32
sys_tmm_flexe_init(uint8 lchip, void* p_cfg)
{
    return CTC_E_NONE;
}

int32
sys_tmm_flexe_deinit(uint8 lchip)
{
    return CTC_E_NONE;
}

